[med-svn] [dcmtkpp] 01/01: Imported Upstream version 0.2.1
Julien Lamy
lamy-guest at moszumanska.debian.org
Thu Jul 16 12:24:31 UTC 2015
This is an automated email from the git hooks/post-receive script.
lamy-guest pushed a commit to branch master
in repository dcmtkpp.
commit f5076a144f10de74fe163338f832cab82276b5f1
Author: Julien Lamy <lamy at picardie.u-strasbg.fr>
Date: Thu Jul 16 14:16:22 2015 +0200
Imported Upstream version 0.2.1
---
.travis.yml | 21 +
CMakeLists.txt | 17 +
Doxyfile | 1813 ++++++++++++++++++
FindICU.cmake | 7 +
LICENSE.txt | 515 ++++++
README.md | 8 +
examples/CMakeLists.txt | 10 +
examples/find.cpp | 76 +
examples/get.cpp | 85 +
examples/move.cpp | 87 +
examples/store.cpp | 60 +
generate_registry | 95 +
src/CMakeLists.txt | 21 +
src/dcmtkpp/Association.cpp | 535 ++++++
src/dcmtkpp/Association.h | 184 ++
src/dcmtkpp/CEchoRequest.cpp | 47 +
src/dcmtkpp/CEchoRequest.h | 47 +
src/dcmtkpp/CEchoResponse.cpp | 49 +
src/dcmtkpp/CEchoResponse.h | 47 +
src/dcmtkpp/CFindRequest.cpp | 65 +
src/dcmtkpp/CFindRequest.h | 48 +
src/dcmtkpp/CFindResponse.cpp | 66 +
src/dcmtkpp/CFindResponse.h | 55 +
src/dcmtkpp/CGetRequest.cpp | 66 +
src/dcmtkpp/CGetRequest.h | 49 +
src/dcmtkpp/CGetResponse.cpp | 79 +
src/dcmtkpp/CGetResponse.h | 64 +
src/dcmtkpp/CMoveRequest.cpp | 69 +
src/dcmtkpp/CMoveRequest.h | 52 +
src/dcmtkpp/CMoveResponse.cpp | 79 +
src/dcmtkpp/CMoveResponse.h | 64 +
src/dcmtkpp/CStoreRequest.cpp | 75 +
src/dcmtkpp/CStoreRequest.h | 61 +
src/dcmtkpp/CStoreResponse.cpp | 59 +
src/dcmtkpp/CStoreResponse.h | 48 +
src/dcmtkpp/Cancellation.cpp | 46 +
src/dcmtkpp/Cancellation.h | 42 +
src/dcmtkpp/DataSet.cpp | 308 ++++
src/dcmtkpp/DataSet.h | 200 ++
src/dcmtkpp/Element.cpp | 236 +++
src/dcmtkpp/Element.h | 212 +++
src/dcmtkpp/Element.txx | 57 +
src/dcmtkpp/ElementAccessor.cpp | 39 +
src/dcmtkpp/ElementAccessor.h | 63 +
src/dcmtkpp/ElementAccessor.txx | 207 +++
src/dcmtkpp/ElementTraits.cpp | 77 +
src/dcmtkpp/ElementTraits.h | 47 +
src/dcmtkpp/Exception.cpp | 71 +
src/dcmtkpp/Exception.h | 66 +
src/dcmtkpp/FindSCU.cpp | 87 +
src/dcmtkpp/FindSCU.h | 42 +
src/dcmtkpp/GetSCU.cpp | 105 ++
src/dcmtkpp/GetSCU.h | 49 +
src/dcmtkpp/Message.cpp | 94 +
src/dcmtkpp/Message.h | 178 ++
src/dcmtkpp/MoveSCU.cpp | 162 ++
src/dcmtkpp/MoveSCU.h | 60 +
src/dcmtkpp/Network.cpp | 201 ++
src/dcmtkpp/Network.h | 91 +
src/dcmtkpp/Request.cpp | 38 +
src/dcmtkpp/Request.h | 43 +
src/dcmtkpp/Response.cpp | 43 +
src/dcmtkpp/Response.h | 44 +
src/dcmtkpp/SCP.cpp | 44 +
src/dcmtkpp/SCP.h | 31 +
src/dcmtkpp/SCU.cpp | 70 +
src/dcmtkpp/SCU.h | 41 +
src/dcmtkpp/ServiceRole.cpp | 632 +++++++
src/dcmtkpp/ServiceRole.h | 114 ++
src/dcmtkpp/ServiceRole.txx | 39 +
src/dcmtkpp/StoreSCP.cpp | 94 +
src/dcmtkpp/StoreSCP.h | 43 +
src/dcmtkpp/StoreSCU.cpp | 209 +++
src/dcmtkpp/StoreSCU.h | 36 +
src/dcmtkpp/Tag.cpp | 198 ++
src/dcmtkpp/Tag.h | 97 +
src/dcmtkpp/VR.cpp | 151 ++
src/dcmtkpp/VR.h | 59 +
src/dcmtkpp/VRTraits.h | 66 +
src/dcmtkpp/Value.cpp | 196 ++
src/dcmtkpp/Value.h | 193 ++
src/dcmtkpp/Value.txx | 54 +
src/dcmtkpp/conversion.cpp | 485 +++++
src/dcmtkpp/conversion.h | 72 +
src/dcmtkpp/conversion.txx | 82 +
src/dcmtkpp/json_converter.cpp | 280 +++
src/dcmtkpp/json_converter.h | 26 +
src/dcmtkpp/registry.h | 3867 +++++++++++++++++++++++++++++++++++++++
src/dcmtkpp/unicode.cpp | 332 ++++
src/dcmtkpp/unicode.h | 25 +
tests/CMakeLists.txt | 41 +
tests/MessageFixtureBase.h | 54 +
tests/PeerFixtureBase.h | 86 +
tests/code/Association.cpp | 251 +++
tests/code/CEchoRequest.cpp | 56 +
tests/code/CEchoResponse.cpp | 58 +
tests/code/CFindRequest.cpp | 83 +
tests/code/CFindResponse.cpp | 72 +
tests/code/CGetRequest.cpp | 80 +
tests/code/CGetResponse.cpp | 94 +
tests/code/CMoveRequest.cpp | 81 +
tests/code/CMoveResponse.cpp | 93 +
tests/code/CStoreRequest.cpp | 88 +
tests/code/CStoreResponse.cpp | 68 +
tests/code/Cancellation.cpp | 40 +
tests/code/DataSet.cpp | 273 +++
tests/code/Element.cpp | 160 ++
tests/code/ElementAccessor.cpp | 125 ++
tests/code/Exception.cpp | 36 +
tests/code/FindSCU.cpp | 65 +
tests/code/GetSCU.cpp | 69 +
tests/code/Message.cpp | 57 +
tests/code/MoveSCU.cpp | 82 +
tests/code/Network.cpp | 156 ++
tests/code/Request.cpp | 27 +
tests/code/Response.cpp | 31 +
tests/code/SCU.cpp | 41 +
tests/code/ServiceRole.cpp | 62 +
tests/code/StoreSCU.cpp | 79 +
tests/code/Tag.cpp | 187 ++
tests/code/VR.cpp | 31 +
tests/code/Value.cpp | 250 +++
tests/code/conversion.cpp | 424 +++++
tests/code/json_converter.cpp | 269 +++
tests/code/unicode.cpp | 258 +++
tests/run.sh | 57 +
126 files changed, 19151 insertions(+)
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b91eb36
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,21 @@
+language: cpp
+compiler:
+ - gcc
+ - clang
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install -y libdcmtk2-dev libwrap0-dev libjsoncpp-dev libicu-dev zlib1g-dev libboost-test-dev dcmtk
+ - sudo pip install cpp-coveralls
+before_script:
+ - export SRC_DIR=$PWD
+ - mkdir build
+ - cd build
+ - export BIN_DIR=$PWD
+ - CMAKE_CXX_FLAGS="-std=c++0x"
+ - if [ "${CC}" = "gcc" ]; then CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} --coverage"; fi
+ - cmake -D CMAKE_CXX_FLAGS:STRING="${CMAKE_CXX_FLAGS}" -D CMAKE_BUILD_TYPE:STRING=Debug ../
+script:
+ - make -j $(nproc)
+ - ../tests/run.sh
+after_success:
+ - if [ "${CC}" = "gcc" ]; then coveralls --exclude examples --exclude tests --exclude-pattern '.*CMake[^/]+\.c(?:pp)?' --exclude-pattern "/usr/.*" --root=${SRC_DIR} --build-root ${BIN_DIR} | grep -vP "^File '.*'$" | grep -vP ":creating '.*'$" | grep -vP "^Lines executed:.*" | sed '/^$/d'; fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..844a5fc
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 2.8)
+project("dcmtkpp")
+
+option(BUILD_EXAMPLES "Build the examples directory." ON)
+
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}" ${CMAKE_MODULE_PATH})
+include(CTest)
+
+add_subdirectory("src")
+
+if(BUILD_EXAMPLES)
+ add_subdirectory("examples")
+endif()
+
+if(BUILD_TESTING)
+ add_subdirectory("tests")
+endif()
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..885d4f2
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,1813 @@
+# Doxyfile 1.7.6.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a 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.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = "dcmtkpp"
+
+# 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 =
+
+# 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 an logo or 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)
+# base path where the generated documentation will be put.
+# 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 = ./doc
+
+# 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 cause performance problems for the file system.
+
+CREATE_SUBDIRS = 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.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) 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.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) 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.
+
+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" "the"
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# 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.
+
+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.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then 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.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then 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.
+
+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 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 if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+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
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+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 comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+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 behaviour.
+# 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 behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+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.
+
+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.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# 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.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+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.
+
+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, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. 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 that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# 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); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip 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.
+
+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 (the default)
+# will make doxygen 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.
+
+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.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) 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.
+
+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).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data 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 (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT 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.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE 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 appear 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.
+
+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 and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# 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.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When 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 (the default) only methods in the interface are included.
+
+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 namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) 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.
+
+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 (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+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 (the default) these declarations will be included in the
+# documentation.
+
+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 (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+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 (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+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.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# 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.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) 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.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# 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 default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# 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 default)
+# the group names will appear in their defined order.
+
+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 default), 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.
+
+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.
+
+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.
+
+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.
+
+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.
+
+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.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of 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 initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+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.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# 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 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 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. See the manual for examples.
+
+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. The 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.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# 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.
+
+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
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED 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.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR 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.
+
+WARN_IF_DOC_ERROR = YES
+
+# The 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 (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+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)
+
+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 stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be 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.
+
+INPUT = ./src/dcmtkpp
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. 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.
+
+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 pattern (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++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.d \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.mm \
+ *.dox \
+ *.py \
+ *.f90 \
+ *.f \
+ *.for \
+ *.vhd \
+ *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# 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 =
+
+# 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.
+
+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 =
+
+# 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
+
+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 =
+
+# 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 = *
+
+# 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.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are 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 <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> 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.
+
+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
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non 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 be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+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 option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# 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 also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+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.
+
+REFERENCED_BY_RELATION = NO
+
+# 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.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# 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.
+
+REFERENCES_LINK_SOURCE = 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.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) 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.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# 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.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# 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 one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+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. If left blank `html' will be used as the default path.
+
+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). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+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 the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# style sheet in the HTML output directory as well, or it will be erased!
+
+HTML_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.
+
+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.
+# The allowed range is 0 to 359.
+
+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.
+
+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.
+
+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 NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# 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. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# 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, 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.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# 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.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, 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.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_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.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+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.
+
+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.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, 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.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, 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.
+
+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.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW 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.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) 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.
+
+ENUM_VALUES_PER_LINE = 4
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# 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.
+
+TREEVIEW_WIDTH = 250
+
+# When 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.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# 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.
+
+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 before the changes have effect.
+
+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 prerendered 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 also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# 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.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# 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.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/FindICU.cmake b/FindICU.cmake
new file mode 100644
index 0000000..57cf7ed
--- /dev/null
+++ b/FindICU.cmake
@@ -0,0 +1,7 @@
+find_path(ICU_INCLUDE_DIR "unicode/ucnv.h")
+# icucore is for OS X
+find_library(ICU_LIBRARIES NAMES icuuc icucore)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(ICU DEFAULT_MSG
+ ICU_INCLUDE_DIR ICU_LIBRARIES)
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..3ad4dea
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,515 @@
+
+CeCILL-B FREE SOFTWARE LICENSE AGREEMENT
+
+
+ Notice
+
+This Agreement is a Free Software license agreement that is the result
+of discussions between its authors in order to ensure compliance with
+the two main principles guiding its drafting:
+
+ * firstly, compliance with the principles governing the distribution
+ of Free Software: access to source code, broad rights granted to
+ users,
+ * secondly, the election of a governing law, French law, with which
+ it is conformant, both as regards the law of torts and
+ intellectual property law, and the protection that it offers to
+ both authors and holders of the economic rights over software.
+
+The authors of the CeCILL-B (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre])
+license are:
+
+Commissariat � l'Energie Atomique - CEA, a public scientific, technical
+and industrial research establishment, having its principal place of
+business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France.
+
+Centre National de la Recherche Scientifique - CNRS, a public scientific
+and technological establishment, having its principal place of business
+at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
+
+Institut National de Recherche en Informatique et en Automatique -
+INRIA, a public scientific and technological establishment, having its
+principal place of business at Domaine de Voluceau, Rocquencourt, BP
+105, 78153 Le Chesnay cedex, France.
+
+
+ Preamble
+
+This Agreement is an open source software license intended to give users
+significant freedom to modify and redistribute the software licensed
+hereunder.
+
+The exercising of this freedom is conditional upon a strong obligation
+of giving credits for everybody that distributes a software
+incorporating a software ruled by the current license so as all
+contributions to be properly identified and acknowledged.
+
+In consideration of access to the source code and the rights to copy,
+modify and redistribute granted by the license, users are provided only
+with a limited warranty and the software's author, the holder of the
+economic rights, and the successive licensors only have limited liability.
+
+In this respect, the risks associated with loading, using, modifying
+and/or developing or reproducing the software by the user are brought to
+the user's attention, given its Free Software status, which may make it
+complicated to use, with the result that its use is reserved for
+developers and experienced professionals having in-depth computer
+knowledge. Users are therefore encouraged to load and test the
+suitability of the software as regards their requirements in conditions
+enabling the security of their systems and/or data to be ensured and,
+more generally, to use and operate it in the same conditions of
+security. This Agreement may be freely reproduced and published,
+provided it is not altered, and that no provisions are either added or
+removed herefrom.
+
+This Agreement may apply to any or all software for which the holder of
+the economic rights decides to submit the use thereof to its provisions.
+
+
+ Article 1 - DEFINITIONS
+
+For the purpose of this Agreement, when the following expressions
+commence with a capital letter, they shall have the following meaning:
+
+Agreement: means this license agreement, and its possible subsequent
+versions and annexes.
+
+Software: means the software in its Object Code and/or Source Code form
+and, where applicable, its documentation, "as is" when the Licensee
+accepts the Agreement.
+
+Initial Software: means the Software in its Source Code and possibly its
+Object Code form and, where applicable, its documentation, "as is" when
+it is first distributed under the terms and conditions of the Agreement.
+
+Modified Software: means the Software modified by at least one
+Contribution.
+
+Source Code: means all the Software's instructions and program lines to
+which access is required so as to modify the Software.
+
+Object Code: means the binary files originating from the compilation of
+the Source Code.
+
+Holder: means the holder(s) of the economic rights over the Initial
+Software.
+
+Licensee: means the Software user(s) having accepted the Agreement.
+
+Contributor: means a Licensee having made at least one Contribution.
+
+Licensor: means the Holder, or any other individual or legal entity, who
+distributes the Software under the Agreement.
+
+Contribution: means any or all modifications, corrections, translations,
+adaptations and/or new functions integrated into the Software by any or
+all Contributors, as well as any or all Internal Modules.
+
+Module: means a set of sources files including their documentation that
+enables supplementary functions or services in addition to those offered
+by the Software.
+
+External Module: means any or all Modules, not derived from the
+Software, so that this Module and the Software run in separate address
+spaces, with one calling the other when they are run.
+
+Internal Module: means any or all Module, connected to the Software so
+that they both execute in the same address space.
+
+Parties: mean both the Licensee and the Licensor.
+
+These expressions may be used both in singular and plural form.
+
+
+ Article 2 - PURPOSE
+
+The purpose of the Agreement is the grant by the Licensor to the
+Licensee of a non-exclusive, transferable and worldwide license for the
+Software as set forth in Article 5 hereinafter for the whole term of the
+protection granted by the rights over said Software.
+
+
+ Article 3 - ACCEPTANCE
+
+3.1 The Licensee shall be deemed as having accepted the terms and
+conditions of this Agreement upon the occurrence of the first of the
+following events:
+
+ * (i) loading the Software by any or all means, notably, by
+ downloading from a remote server, or by loading from a physical
+ medium;
+ * (ii) the first time the Licensee exercises any of the rights
+ granted hereunder.
+
+3.2 One copy of the Agreement, containing a notice relating to the
+characteristics of the Software, to the limited warranty, and to the
+fact that its use is restricted to experienced users has been provided
+to the Licensee prior to its acceptance as set forth in Article 3.1
+hereinabove, and the Licensee hereby acknowledges that it has read and
+understood it.
+
+
+ Article 4 - EFFECTIVE DATE AND TERM
+
+
+ 4.1 EFFECTIVE DATE
+
+The Agreement shall become effective on the date when it is accepted by
+the Licensee as set forth in Article 3.1.
+
+
+ 4.2 TERM
+
+The Agreement shall remain in force for the entire legal term of
+protection of the economic rights over the Software.
+
+
+ Article 5 - SCOPE OF RIGHTS GRANTED
+
+The Licensor hereby grants to the Licensee, who accepts, the following
+rights over the Software for any or all use, and for the term of the
+Agreement, on the basis of the terms and conditions set forth hereinafter.
+
+Besides, if the Licensor owns or comes to own one or more patents
+protecting all or part of the functions of the Software or of its
+components, the Licensor undertakes not to enforce the rights granted by
+these patents against successive Licensees using, exploiting or
+modifying the Software. If these patents are transferred, the Licensor
+undertakes to have the transferees subscribe to the obligations set
+forth in this paragraph.
+
+
+ 5.1 RIGHT OF USE
+
+The Licensee is authorized to use the Software, without any limitation
+as to its fields of application, with it being hereinafter specified
+that this comprises:
+
+ 1. permanent or temporary reproduction of all or part of the Software
+ by any or all means and in any or all form.
+
+ 2. loading, displaying, running, or storing the Software on any or
+ all medium.
+
+ 3. entitlement to observe, study or test its operation so as to
+ determine the ideas and principles behind any or all constituent
+ elements of said Software. This shall apply when the Licensee
+ carries out any or all loading, displaying, running, transmission
+ or storage operation as regards the Software, that it is entitled
+ to carry out hereunder.
+
+
+ 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS
+
+The right to make Contributions includes the right to translate, adapt,
+arrange, or make any or all modifications to the Software, and the right
+to reproduce the resulting software.
+
+The Licensee is authorized to make any or all Contributions to the
+Software provided that it includes an explicit notice that it is the
+author of said Contribution and indicates the date of the creation thereof.
+
+
+ 5.3 RIGHT OF DISTRIBUTION
+
+In particular, the right of distribution includes the right to publish,
+transmit and communicate the Software to the general public on any or
+all medium, and by any or all means, and the right to market, either in
+consideration of a fee, or free of charge, one or more copies of the
+Software by any means.
+
+The Licensee is further authorized to distribute copies of the modified
+or unmodified Software to third parties according to the terms and
+conditions set forth hereinafter.
+
+
+ 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
+
+The Licensee is authorized to distribute true copies of the Software in
+Source Code or Object Code form, provided that said distribution
+complies with all the provisions of the Agreement and is accompanied by:
+
+ 1. a copy of the Agreement,
+
+ 2. a notice relating to the limitation of both the Licensor's
+ warranty and liability as set forth in Articles 8 and 9,
+
+and that, in the event that only the Object Code of the Software is
+redistributed, the Licensee allows effective access to the full Source
+Code of the Software at a minimum during the entire period of its
+distribution of the Software, it being understood that the additional
+cost of acquiring the Source Code shall not exceed the cost of
+transferring the data.
+
+
+ 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
+
+If the Licensee makes any Contribution to the Software, the resulting
+Modified Software may be distributed under a license agreement other
+than this Agreement subject to compliance with the provisions of Article
+5.3.4.
+
+
+ 5.3.3 DISTRIBUTION OF EXTERNAL MODULES
+
+When the Licensee has developed an External Module, the terms and
+conditions of this Agreement do not apply to said External Module, that
+may be distributed under a separate license agreement.
+
+
+ 5.3.4 CREDITS
+
+Any Licensee who may distribute a Modified Software hereby expressly
+agrees to:
+
+ 1. indicate in the related documentation that it is based on the
+ Software licensed hereunder, and reproduce the intellectual
+ property notice for the Software,
+
+ 2. ensure that written indications of the Software intended use,
+ intellectual property notice and license hereunder are included in
+ easily accessible format from the Modified Software interface,
+
+ 3. mention, on a freely accessible website describing the Modified
+ Software, at least throughout the distribution term thereof, that
+ it is based on the Software licensed hereunder, and reproduce the
+ Software intellectual property notice,
+
+ 4. where it is distributed to a third party that may distribute a
+ Modified Software without having to make its source code
+ available, make its best efforts to ensure that said third party
+ agrees to comply with the obligations set forth in this Article .
+
+If the Software, whether or not modified, is distributed with an
+External Module designed for use in connection with the Software, the
+Licensee shall submit said External Module to the foregoing obligations.
+
+
+ 5.3.5 COMPATIBILITY WITH THE CeCILL AND CeCILL-C LICENSES
+
+Where a Modified Software contains a Contribution subject to the CeCILL
+license, the provisions set forth in Article 5.3.4 shall be optional.
+
+A Modified Software may be distributed under the CeCILL-C license. In
+such a case the provisions set forth in Article 5.3.4 shall be optional.
+
+
+ Article 6 - INTELLECTUAL PROPERTY
+
+
+ 6.1 OVER THE INITIAL SOFTWARE
+
+The Holder owns the economic rights over the Initial Software. Any or
+all use of the Initial Software is subject to compliance with the terms
+and conditions under which the Holder has elected to distribute its work
+and no one shall be entitled to modify the terms and conditions for the
+distribution of said Initial Software.
+
+The Holder undertakes that the Initial Software will remain ruled at
+least by this Agreement, for the duration set forth in Article 4.2.
+
+
+ 6.2 OVER THE CONTRIBUTIONS
+
+The Licensee who develops a Contribution is the owner of the
+intellectual property rights over this Contribution as defined by
+applicable law.
+
+
+ 6.3 OVER THE EXTERNAL MODULES
+
+The Licensee who develops an External Module is the owner of the
+intellectual property rights over this External Module as defined by
+applicable law and is free to choose the type of agreement that shall
+govern its distribution.
+
+
+ 6.4 JOINT PROVISIONS
+
+The Licensee expressly undertakes:
+
+ 1. not to remove, or modify, in any manner, the intellectual property
+ notices attached to the Software;
+
+ 2. to reproduce said notices, in an identical manner, in the copies
+ of the Software modified or not.
+
+The Licensee undertakes not to directly or indirectly infringe the
+intellectual property rights of the Holder and/or Contributors on the
+Software and to take, where applicable, vis-�-vis its staff, any and all
+measures required to ensure respect of said intellectual property rights
+of the Holder and/or Contributors.
+
+
+ Article 7 - RELATED SERVICES
+
+7.1 Under no circumstances shall the Agreement oblige the Licensor to
+provide technical assistance or maintenance services for the Software.
+
+However, the Licensor is entitled to offer this type of services. The
+terms and conditions of such technical assistance, and/or such
+maintenance, shall be set forth in a separate instrument. Only the
+Licensor offering said maintenance and/or technical assistance services
+shall incur liability therefor.
+
+7.2 Similarly, any Licensor is entitled to offer to its licensees, under
+its sole responsibility, a warranty, that shall only be binding upon
+itself, for the redistribution of the Software and/or the Modified
+Software, under terms and conditions that it is free to decide. Said
+warranty, and the financial terms and conditions of its application,
+shall be subject of a separate instrument executed between the Licensor
+and the Licensee.
+
+
+ Article 8 - LIABILITY
+
+8.1 Subject to the provisions of Article 8.2, the Licensee shall be
+entitled to claim compensation for any direct loss it may have suffered
+from the Software as a result of a fault on the part of the relevant
+Licensor, subject to providing evidence thereof.
+
+8.2 The Licensor's liability is limited to the commitments made under
+this Agreement and shall not be incurred as a result of in particular:
+(i) loss due the Licensee's total or partial failure to fulfill its
+obligations, (ii) direct or consequential loss that is suffered by the
+Licensee due to the use or performance of the Software, and (iii) more
+generally, any consequential loss. In particular the Parties expressly
+agree that any or all pecuniary or business loss (i.e. loss of data,
+loss of profits, operating loss, loss of customers or orders,
+opportunity cost, any disturbance to business activities) or any or all
+legal proceedings instituted against the Licensee by a third party,
+shall constitute consequential loss and shall not provide entitlement to
+any or all compensation from the Licensor.
+
+
+ Article 9 - WARRANTY
+
+9.1 The Licensee acknowledges that the scientific and technical
+state-of-the-art when the Software was distributed did not enable all
+possible uses to be tested and verified, nor for the presence of
+possible defects to be detected. In this respect, the Licensee's
+attention has been drawn to the risks associated with loading, using,
+modifying and/or developing and reproducing the Software which are
+reserved for experienced users.
+
+The Licensee shall be responsible for verifying, by any or all means,
+the suitability of the product for its requirements, its good working
+order, and for ensuring that it shall not cause damage to either persons
+or properties.
+
+9.2 The Licensor hereby represents, in good faith, that it is entitled
+to grant all the rights over the Software (including in particular the
+rights set forth in Article 5).
+
+9.3 The Licensee acknowledges that the Software is supplied "as is" by
+the Licensor without any other express or tacit warranty, other than
+that provided for in Article 9.2 and, in particular, without any warranty
+as to its commercial value, its secured, safe, innovative or relevant
+nature.
+
+Specifically, the Licensor does not warrant that the Software is free
+from any error, that it will operate without interruption, that it will
+be compatible with the Licensee's own equipment and software
+configuration, nor that it will meet the Licensee's requirements.
+
+9.4 The Licensor does not either expressly or tacitly warrant that the
+Software does not infringe any third party intellectual property right
+relating to a patent, software or any other property right. Therefore,
+the Licensor disclaims any and all liability towards the Licensee
+arising out of any or all proceedings for infringement that may be
+instituted in respect of the use, modification and redistribution of the
+Software. Nevertheless, should such proceedings be instituted against
+the Licensee, the Licensor shall provide it with technical and legal
+assistance for its defense. Such technical and legal assistance shall be
+decided on a case-by-case basis between the relevant Licensor and the
+Licensee pursuant to a memorandum of understanding. The Licensor
+disclaims any and all liability as regards the Licensee's use of the
+name of the Software. No warranty is given as regards the existence of
+prior rights over the name of the Software or as regards the existence
+of a trademark.
+
+
+ Article 10 - TERMINATION
+
+10.1 In the event of a breach by the Licensee of its obligations
+hereunder, the Licensor may automatically terminate this Agreement
+thirty (30) days after notice has been sent to the Licensee and has
+remained ineffective.
+
+10.2 A Licensee whose Agreement is terminated shall no longer be
+authorized to use, modify or distribute the Software. However, any
+licenses that it may have granted prior to termination of the Agreement
+shall remain valid subject to their having been granted in compliance
+with the terms and conditions hereof.
+
+
+ Article 11 - MISCELLANEOUS
+
+
+ 11.1 EXCUSABLE EVENTS
+
+Neither Party shall be liable for any or all delay, or failure to
+perform the Agreement, that may be attributable to an event of force
+majeure, an act of God or an outside cause, such as defective
+functioning or interruptions of the electricity or telecommunications
+networks, network paralysis following a virus attack, intervention by
+government authorities, natural disasters, water damage, earthquakes,
+fire, explosions, strikes and labor unrest, war, etc.
+
+11.2 Any failure by either Party, on one or more occasions, to invoke
+one or more of the provisions hereof, shall under no circumstances be
+interpreted as being a waiver by the interested Party of its right to
+invoke said provision(s) subsequently.
+
+11.3 The Agreement cancels and replaces any or all previous agreements,
+whether written or oral, between the Parties and having the same
+purpose, and constitutes the entirety of the agreement between said
+Parties concerning said purpose. No supplement or modification to the
+terms and conditions hereof shall be effective as between the Parties
+unless it is made in writing and signed by their duly authorized
+representatives.
+
+11.4 In the event that one or more of the provisions hereof were to
+conflict with a current or future applicable act or legislative text,
+said act or legislative text shall prevail, and the Parties shall make
+the necessary amendments so as to comply with said act or legislative
+text. All other provisions shall remain effective. Similarly, invalidity
+of a provision of the Agreement, for any reason whatsoever, shall not
+cause the Agreement as a whole to be invalid.
+
+
+ 11.5 LANGUAGE
+
+The Agreement is drafted in both French and English and both versions
+are deemed authentic.
+
+
+ Article 12 - NEW VERSIONS OF THE AGREEMENT
+
+12.1 Any person is authorized to duplicate and distribute copies of this
+Agreement.
+
+12.2 So as to ensure coherence, the wording of this Agreement is
+protected and may only be modified by the authors of the License, who
+reserve the right to periodically publish updates or new versions of the
+Agreement, each with a separate number. These subsequent versions may
+address new issues encountered by Free Software.
+
+12.3 Any Software distributed under a given version of the Agreement may
+only be subsequently distributed under the same version of the Agreement
+or a subsequent version.
+
+
+ Article 13 - GOVERNING LAW AND JURISDICTION
+
+13.1 The Agreement is governed by French law. The Parties agree to
+endeavor to seek an amicable solution to any disagreements or disputes
+that may arise during the performance of the Agreement.
+
+13.2 Failing an amicable solution within two (2) months as from their
+occurrence, and unless emergency proceedings are necessary, the
+disagreements or disputes shall be referred to the Paris Courts having
+jurisdiction, by the more diligent Party.
+
+
+Version 1.0 dated 2006-09-05.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c4fb856
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+DCMTK++
+=======
+
+DCMTK++ is a set of wrappers around [DCMTK](http://dicom.offis.de/dcmtk.php.en)
+to have an easier API, notably for the networking part.
+
+[![Build Status](https://travis-ci.org/lamyj/dcmtkpp.svg?branch=master)](https://travis-ci.org/lamyj/dcmtkpp)
+[![Coverage Status](https://coveralls.io/repos/lamyj/dcmtkpp/badge.svg)](https://coveralls.io/r/lamyj/dcmtkpp)
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000..0764cb3
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_definitions("-D HAVE_CONFIG_H")
+
+include_directories(${CMAKE_SOURCE_DIR}/src)
+
+set(examples find get move store)
+
+foreach(example ${examples})
+ add_executable(${example} ${example}.cpp)
+ target_link_libraries(${example} dcmtkpp dcmdata)
+endforeach()
diff --git a/examples/find.cpp b/examples/find.cpp
new file mode 100644
index 0000000..321b15c
--- /dev/null
+++ b/examples/find.cpp
@@ -0,0 +1,76 @@
+#include <iostream>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dctk.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/FindSCU.h"
+#include "dcmtkpp/registry.h"
+
+void print_informations(dcmtkpp::DataSet const & response)
+{
+ std::cout << response.as_string("PatientName", 0) << ": "
+ << response.as_string("StudyDescription", 0)
+ << " on " << response.as_string("StudyDate", 0) << ", "
+ << response.as_int(dcmtkpp::registry::NumberOfStudyRelatedSeries, 0) << " series\n";
+}
+
+int main()
+{
+ dcmtkpp::Network network;
+ network.initialize();
+
+ dcmtkpp::Association association;
+
+ association.set_own_ae_title("myself");
+
+ association.set_peer_host_name("pacs.example.com");
+ association.set_peer_port(11112);
+ association.set_peer_ae_title("pacs");
+
+ association.add_presentation_context(
+ UID_FINDStudyRootQueryRetrieveInformationModel,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.add_presentation_context(
+ UID_VerificationSOPClass,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.associate(network);
+
+ dcmtkpp::FindSCU scu;
+ scu.set_network(&network);
+ scu.set_association(&association);
+
+ scu.echo();
+
+ dcmtkpp::DataSet query;
+ query.add("PatientName", { "DOE^John" });
+ query.add("QueryRetrieveLevel", { "STUDY" });
+ query.add("StudyDescription");
+ query.add(dcmtkpp::registry::NumberOfStudyRelatedSeries);
+ query.add("StudyDate");
+
+ scu.set_affected_sop_class(UID_FINDStudyRootQueryRetrieveInformationModel);
+
+ std::cout << "--------\n";
+ std::cout << "Callback\n";
+ std::cout << "--------\n\n";
+
+ scu.find(query, print_informations);
+
+ std::cout << "\n";
+
+ std::cout << "------\n";
+ std::cout << "vector\n";
+ std::cout << "------\n\n";
+
+ std::vector<dcmtkpp::DataSet> result = scu.find(query);
+ for(auto dataset: result)
+ {
+ print_informations(dataset);
+ }
+
+ association.release();
+ network.drop();
+}
diff --git a/examples/get.cpp b/examples/get.cpp
new file mode 100644
index 0000000..f50690e
--- /dev/null
+++ b/examples/get.cpp
@@ -0,0 +1,85 @@
+#include <iostream>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dctk.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/GetSCU.h"
+#include "dcmtkpp/registry.h"
+
+void print_informations(dcmtkpp::DataSet const & response)
+{
+ std::cout
+ << response.as_string("PatientName", 0)
+ << ": "
+ << response.as_string("StudyDescription", 0)
+ << " / "
+ << response.as_string("SeriesDescription", 0)
+ << ": "
+ << response.as_string("InstanceNumber", 0)
+ << "\n";
+}
+
+int main()
+{
+ dcmtkpp::Network network;
+ network.initialize();
+
+ dcmtkpp::Association association;
+
+ association.set_own_ae_title("myself");
+
+ association.set_peer_host_name("pacs.example.com");
+ association.set_peer_port(11112);
+ association.set_peer_ae_title("pacs");
+
+ association.add_presentation_context(
+ UID_GETStudyRootQueryRetrieveInformationModel,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.add_presentation_context(
+ UID_MRImageStorage,
+ { UID_LittleEndianImplicitTransferSyntax },
+ ASC_SC_ROLE_SCP);
+
+ association.add_presentation_context(
+ UID_VerificationSOPClass,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.associate(network);
+
+ dcmtkpp::GetSCU scu;
+ scu.set_network(&network);
+ scu.set_association(&association);
+
+ scu.echo();
+
+ dcmtkpp::DataSet query;
+ query.add("PatientID",{ "1234" });
+ query.add("QueryRetrieveLevel", { "SERIES" });
+ query.add("StudyInstanceUID", { "1.2.3.4.5" });
+ query.add("SeriesInstanceUID", { "1.2.3.4.5.1" });
+
+ scu.set_affected_sop_class(UID_GETStudyRootQueryRetrieveInformationModel);
+
+ std::cout << "--------\n";
+ std::cout << "Callback\n";
+ std::cout << "--------\n\n";
+
+ scu.get(query, print_informations);
+
+ std::cout << "\n";
+
+ std::cout << "------\n";
+ std::cout << "vector\n";
+ std::cout << "------\n\n";
+
+ std::vector<dcmtkpp::DataSet> result = scu.get(query);
+ for(auto dataset: result)
+ {
+ print_informations(dataset);
+ }
+
+ association.release();
+ network.drop();
+}
diff --git a/examples/move.cpp b/examples/move.cpp
new file mode 100644
index 0000000..fb8b12d
--- /dev/null
+++ b/examples/move.cpp
@@ -0,0 +1,87 @@
+#include <iostream>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dctk.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/MoveSCU.h"
+#include "dcmtkpp/registry.h"
+
+void print_informations(dcmtkpp::DataSet const & response)
+{
+ std::cout
+ << response.as_string("PatientName", 0)
+ << ": "
+ << response.as_string("StudyDescription", 0)
+ << " / "
+ << response.as_string("SeriesDescription", 0)
+ << ": "
+ << response.as_string("InstanceNumber", 0)
+ << "\n";
+}
+
+int main()
+{
+ dcmtkpp::Network network;
+ network.set_role(NET_ACCEPTORREQUESTOR);
+ network.set_port(11112);
+ network.initialize();
+
+ dcmtkpp::Association association;
+ association.set_own_ae_title("myself");
+
+ association.set_peer_host_name("pacs.example.com");
+ association.set_peer_port(11112);
+ association.set_peer_ae_title("pacs");
+
+ association.add_presentation_context(
+ UID_MOVEStudyRootQueryRetrieveInformationModel,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.add_presentation_context(
+ UID_MRImageStorage,
+ { UID_LittleEndianImplicitTransferSyntax },
+ ASC_SC_ROLE_SCP);
+
+ association.add_presentation_context(
+ UID_VerificationSOPClass,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.associate(network);
+
+ dcmtkpp::MoveSCU scu;
+ scu.set_network(&network);
+ scu.set_association(&association);
+ scu.set_move_destination(association.get_own_ae_title());
+
+ scu.echo();
+
+ dcmtkpp::DataSet query;
+ query.add("PatientID",{ "1234" });
+ query.add("QueryRetrieveLevel", { "SERIES" });
+ query.add("StudyInstanceUID", { "1.2.3.4.5" });
+ query.add("SeriesInstanceUID", { "1.2.3.4.5.1" });
+
+ scu.set_affected_sop_class(UID_MOVEStudyRootQueryRetrieveInformationModel);
+
+ std::cout << "--------\n";
+ std::cout << "Callback\n";
+ std::cout << "--------\n\n";
+
+ scu.move(query, print_informations);
+
+ std::cout << "\n";
+
+ std::cout << "------\n";
+ std::cout << "vector\n";
+ std::cout << "------\n\n";
+
+ std::vector<dcmtkpp::DataSet> result = scu.move(query);
+ for(auto dataset: result)
+ {
+ print_informations(dataset);
+ }
+
+ association.release();
+ network.drop();
+}
diff --git a/examples/store.cpp b/examples/store.cpp
new file mode 100644
index 0000000..184da07
--- /dev/null
+++ b/examples/store.cpp
@@ -0,0 +1,60 @@
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dctk.h>
+
+#include "dcmtkpp/conversion.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/StoreSCU.h"
+
+void progress_callback(void * data, unsigned long bytes_count)
+{
+ long file_size = *reinterpret_cast<long*>(data);
+ std::cout << bytes_count << "/" << file_size << std::endl;
+}
+
+int main(int argc, char** argv)
+{
+ dcmtkpp::Network network;
+ network.initialize();
+
+ dcmtkpp::Association association;
+
+ association.set_own_ae_title("myself");
+
+ association.set_peer_host_name("pacs.example.com");
+ association.set_peer_port(11112);
+ association.set_peer_ae_title("pacs");
+
+ association.add_presentation_context(UID_MRImageStorage,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.add_presentation_context(UID_EnhancedMRImageStorage,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.add_presentation_context(UID_VerificationSOPClass,
+ { UID_LittleEndianImplicitTransferSyntax });
+
+ association.associate(network);
+
+ dcmtkpp::StoreSCU scu;
+ scu.set_network(&network);
+ scu.set_association(&association);
+
+ scu.echo();
+
+ for(int i=1; i<argc; ++i)
+ {
+ std::cout << "Storing " << argv[i] << std::endl;
+
+ long file_size = OFStandard::getFileSize(argv[i]);
+ DcmFileFormat file;
+ file.loadFile(argv[i]);
+
+ dcmtkpp::DataSet const data_set = dcmtkpp::convert(file.getDataset());
+
+ scu.set_affected_sop_class(data_set);
+ scu.store(data_set, progress_callback, &file_size);
+ }
+
+ association.release();
+ network.drop();
+}
diff --git a/generate_registry b/generate_registry
new file mode 100755
index 0000000..e0a3f16
--- /dev/null
+++ b/generate_registry
@@ -0,0 +1,95 @@
+#! /usr/bin/env python
+
+import re
+import urllib
+import sys
+import xml.etree.ElementTree
+
+def main():
+ sources = [
+ ("http://medical.nema.org/medical/dicom/current/source/docbook/part07/part07.xml", "table_E.1-1"),
+ ("http://medical.nema.org/medical/dicom/current/source/docbook/part06/part06.xml", "table_7-1"),
+ ("http://medical.nema.org/medical/dicom/current/source/docbook/part06/part06.xml", "table_8-1"),
+ ("http://medical.nema.org/medical/dicom/current/source/docbook/part06/part06.xml", "table_6-1"),
+
+ ]
+
+ header = [
+ "/*************************************************************************",
+ "* dcmtkpp - Copyright (C) Universite de Strasbourg",
+ "* Distributed under the terms of the CeCILL-B license, as published by",
+ "* the CEA-CNRS-INRIA. Refer to the LICENSE file or to",
+ "* http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html",
+ "* for details.",
+ "************************************************************************/",
+ "",
+ "#ifndef _afc7b2d7_0869_4fea_9a9b_7fe6228baca9",
+ "#define _afc7b2d7_0869_4fea_9a9b_7fe6228baca9",
+ "",
+ "#include \"dcmtkpp/Tag.h\"",
+ "",
+ "namespace dcmtkpp",
+ "{",
+ "",
+ "namespace registry",
+ "{",
+ ]
+
+ declarations = []
+ for url, id_ in sources:
+ declarations.extend(generate_registry(url, id_))
+
+ footer = [
+ "}",
+ "",
+ "}",
+ "",
+ "#endif // _afc7b2d7_0869_4fea_9a9b_7fe6228baca9",
+ ]
+
+ print "\n".join(header+declarations+footer)
+
+ return 0
+
+def generate_registry(url, id_):
+ fd = urllib.urlopen(url)
+ document = xml.etree.ElementTree.parse(fd)
+ fd.close()
+
+ namespaces = {
+ "xml": "http://www.w3.org/XML/1998/namespace",
+ "docbook": "http://docbook.org/ns/docbook"
+ }
+
+ table = document.find(".//*[@xml:id=\"{}\"]".format(id_), namespaces)
+
+ entries = []
+
+ for row in table.iterfind("./docbook:tbody/docbook:tr", namespaces):
+ entry = row.findall("./docbook:td/docbook:para", namespaces)
+ tag = entry[0]
+ if tag.getchildren():
+ tag = tag.find("./docbook:emphasis", namespaces)
+ tag = tag.text
+
+ match = re.match(r"\(([0-9a-fA-F]{4}),([0-9a-fA-F]{4})\)", tag)
+ if not match:
+ continue
+
+ tag = [int(x, 16) for x in match.groups()]
+
+ keyword = entry[2]
+ if keyword.getchildren():
+ keyword = keyword.find("./docbook:emphasis", namespaces)
+ keyword = keyword.text or ""
+ keyword = keyword.replace(u"\u200b", "").decode("ascii")
+ if not keyword:
+ continue
+
+ entries.append(" Tag const {}(0x{:04x}, 0x{:04x});".format(keyword, *tag))
+
+ return entries
+
+if __name__ == "__main__":
+ sys.exit(main())
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..92306ef
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,21 @@
+find_package(ICU REQUIRED)
+
+set(DCMTK_LIBRARIES dcmnet dcmdata oflog ofstd pthread z)
+find_library(USE_WRAP wrap)
+if(USE_WRAP)
+ set(DCMTK_LIBRARIES ${DCMTK_LIBRARIES} wrap)
+endif()
+
+file(GLOB_RECURSE headers "*.h")
+file(GLOB_RECURSE templates "*.txx")
+file(GLOB_RECURSE files "*.cpp")
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ICU_INCLUDE_DIR})
+add_definitions("-D HAVE_CONFIG_H")
+
+add_library(dcmtkpp SHARED ${files})
+install(TARGETS dcmtkpp LIBRARY DESTINATION lib)
+install(FILES ${headers} ${templates} DESTINATION include/dcmtkpp)
+
+target_link_libraries(dcmtkpp ${DCMTK_LIBRARIES} jsoncpp ${ICU_LIBRARIES})
+
+
diff --git a/src/dcmtkpp/Association.cpp b/src/dcmtkpp/Association.cpp
new file mode 100644
index 0000000..d60dec2
--- /dev/null
+++ b/src/dcmtkpp/Association.cpp
@@ -0,0 +1,535 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "Association.h"
+
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/assoc.h>
+#include <dcmtk/dcmnet/cond.h>
+
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+Association
+::Association()
+: _own_ae_title(""),
+ _peer_host_name(""), _peer_port(104), _peer_ae_title(""),
+ _user_identity_type(UserIdentityType::None),
+ _user_identity_primary_field(""), _user_identity_secondary_field(""),
+ _association(NULL)
+{
+ // Nothing else
+}
+
+Association
+::Association(Association const & other)
+: _own_ae_title(other.get_own_ae_title()),
+ _peer_host_name(other.get_peer_host_name()), _peer_port(other.get_peer_port()),
+ _peer_ae_title(other.get_peer_ae_title()),
+ _user_identity_type(other.get_user_identity_type()),
+ _user_identity_primary_field(other.get_user_identity_primary_field()),
+ _user_identity_secondary_field(other.get_user_identity_secondary_field()),
+ _association(NULL)
+{
+}
+
+Association
+::~Association()
+{
+ if(this->is_associated())
+ {
+ this->release();
+ }
+}
+
+Association &
+Association
+::operator=(Association const & other)
+{
+ if(this != &other)
+ {
+ this->set_own_ae_title(other.get_own_ae_title());
+ this->set_peer_host_name(other.get_peer_host_name());
+ this->set_peer_port(other.get_peer_port());
+ this->set_peer_ae_title(other.get_peer_ae_title());
+ this->set_user_identity_type(other.get_user_identity_type());
+ this->set_user_identity_primary_field(other.get_user_identity_primary_field());
+ this->set_user_identity_secondary_field(other.get_user_identity_secondary_field());
+ }
+
+ return *this;
+}
+
+std::string const &
+Association
+::get_own_ae_title() const
+{
+ return this->_own_ae_title;
+}
+
+void
+Association
+::set_own_ae_title(std::string const & ae_title)
+{
+ if(this->is_associated())
+ {
+ throw Exception("Cannot set member while associated");
+ }
+
+ this->_own_ae_title = ae_title;
+}
+
+std::string const &
+Association
+::get_peer_host_name() const
+{
+ return this->_peer_host_name;
+}
+
+void
+Association
+::set_peer_host_name(std::string const & host_name)
+{
+ if(this->is_associated())
+ {
+ throw Exception("Cannot set member while associated");
+ }
+
+ this->_peer_host_name = host_name;
+}
+
+uint16_t
+Association
+::get_peer_port() const
+{
+ return this->_peer_port;
+}
+
+void
+Association
+::set_peer_port(uint16_t port)
+{
+ if(this->is_associated())
+ {
+ throw Exception("Cannot set member while associated");
+ }
+
+ this->_peer_port = port;
+}
+
+std::string const &
+Association
+::get_peer_ae_title() const
+{
+ return this->_peer_ae_title;
+}
+
+void
+Association
+::set_peer_ae_title(std::string const & ae_title)
+{
+ if(this->is_associated())
+ {
+ throw Exception("Cannot set member while associated");
+ }
+
+ this->_peer_ae_title = ae_title;
+}
+
+void
+Association
+::add_presentation_context(std::string const & abstract_syntax,
+ std::vector<std::string> const & transfer_syntaxes, T_ASC_SC_ROLE role)
+{
+ if(this->is_associated())
+ {
+ throw Exception("Cannot set member while associated");
+ }
+
+ this->_presentation_contexts.push_back(
+ {abstract_syntax, transfer_syntaxes, role});
+}
+
+UserIdentityType
+Association
+::get_user_identity_type() const
+{
+ return this->_user_identity_type;
+}
+
+void
+Association
+::set_user_identity_type(UserIdentityType type)
+{
+ if(this->is_associated())
+ {
+ throw Exception("Cannot set member while associated");
+ }
+
+ this->_user_identity_type = type;
+}
+
+std::string const &
+Association
+::get_user_identity_primary_field() const
+{
+ return this->_user_identity_primary_field;
+}
+
+void
+Association
+::set_user_identity_primary_field(std::string const & value)
+{
+ if(this->is_associated())
+ {
+ throw Exception("Cannot set member while associated");
+ }
+
+ this->_user_identity_primary_field = value;
+}
+
+std::string const &
+Association
+::get_user_identity_secondary_field() const
+{
+ return this->_user_identity_secondary_field;
+}
+
+void
+Association
+::set_user_identity_secondary_field(std::string const & value)
+{
+ if(this->is_associated())
+ {
+ throw Exception("Cannot set member while associated");
+ }
+
+ this->_user_identity_secondary_field = value;
+}
+
+void
+Association
+::set_user_identity_to_none()
+{
+ this->set_user_identity_type(UserIdentityType::None);
+ this->set_user_identity_primary_field("");
+ this->set_user_identity_secondary_field("");
+}
+
+void
+Association
+::set_user_identity_to_username(std::string const & username)
+{
+ this->set_user_identity_type(UserIdentityType::Username);
+ this->set_user_identity_primary_field(username);
+ this->set_user_identity_secondary_field("");
+}
+
+void
+Association
+::set_user_identity_to_username_and_password(
+ std::string const & username, std::string const & password)
+{
+ this->set_user_identity_type(UserIdentityType::UsernameAndPassword);
+ this->set_user_identity_primary_field(username);
+ this->set_user_identity_secondary_field(password);
+}
+
+void
+Association
+::set_user_identity_to_kerberos(std::string const & ticket)
+{
+ this->set_user_identity_type(UserIdentityType::Kerberos);
+ this->set_user_identity_primary_field(ticket);
+ this->set_user_identity_secondary_field("");
+}
+
+void
+Association
+::set_user_identity_to_saml(std::string const & assertion)
+{
+ this->set_user_identity_type(UserIdentityType::SAML);
+ this->set_user_identity_primary_field(assertion);
+ this->set_user_identity_secondary_field("");
+}
+
+bool
+Association
+::is_associated() const
+{
+ return (this->_association != NULL);
+}
+
+void
+Association
+::associate(Network & network)
+{
+ if(!network.is_initialized())
+ {
+ throw Exception("Network is not initialized");
+ }
+
+ if(this->is_associated())
+ {
+ throw Exception("Already associated");
+ }
+
+ OFCondition condition;
+
+ T_ASC_Parameters * params;
+ condition = ASC_createAssociationParameters(¶ms, ASC_MAXIMUMPDUSIZE);
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+
+ condition = ASC_setAPTitles(params,
+ this->_own_ae_title.c_str(), this->_peer_ae_title.c_str(), NULL);
+ if(condition.bad())
+ {
+ ASC_destroyAssociationParameters(¶ms);
+ throw Exception(condition);
+ }
+
+ std::string localhost(128, '\0');
+ gethostname(&localhost[0], localhost.size()-1);
+
+ std::ostringstream peer;
+ peer << this->_peer_host_name << ":" << this->_peer_port;
+
+ condition = ASC_setPresentationAddresses(params,
+ "localhost", peer.str().c_str());
+ if(condition.bad())
+ {
+ ASC_destroyAssociationParameters(¶ms);
+ throw Exception(condition);
+ }
+
+ unsigned int context_id = 1;
+ for(auto const & context: this->_presentation_contexts)
+ {
+ char const ** transfer_syntaxes = new char const *[context.transfer_syntaxes.size()];
+ for(std::size_t i = 0; i < context.transfer_syntaxes.size(); ++i)
+ {
+ transfer_syntaxes[i] = context.transfer_syntaxes[i].c_str();
+ }
+
+ condition = ASC_addPresentationContext(params,
+ context_id, context.abstract_syntax.c_str(),
+ transfer_syntaxes, context.transfer_syntaxes.size(), context.role);
+ if(condition.bad())
+ {
+ ASC_destroyAssociationParameters(¶ms);
+ throw Exception(condition);
+ }
+
+ context_id += 2;
+ }
+
+ if(this->_user_identity_type == UserIdentityType::None)
+ {
+ // Nothing to do.
+ }
+ else if(this->_user_identity_type == UserIdentityType::Username)
+ {
+ condition = ASC_setIdentRQUserOnly(params,
+ this->_user_identity_primary_field.c_str());
+ }
+ else if(this->_user_identity_type == UserIdentityType::UsernameAndPassword)
+ {
+ condition = ASC_setIdentRQUserOnly(params,
+ this->_user_identity_primary_field.c_str(),
+ this->_user_identity_secondary_field.c_str());
+ }
+ else if(this->_user_identity_type == UserIdentityType::Kerberos)
+ {
+ condition = ASC_setIdentRQKerberos(params,
+ this->_user_identity_primary_field.c_str(),
+ this->_user_identity_primary_field.size());
+ }
+ else if(this->_user_identity_type == UserIdentityType::SAML)
+ {
+ condition = ASC_setIdentRQSaml(params,
+ this->_user_identity_primary_field.c_str(),
+ this->_user_identity_primary_field.size());
+ }
+ else
+ {
+ ASC_destroyAssociationParameters(¶ms);
+ throw Exception("Unknown identity type");
+ }
+
+ if(condition.bad())
+ {
+ ASC_destroyAssociationParameters(¶ms);
+ throw Exception(condition);
+ }
+
+ condition = ASC_requestAssociation(
+ network.get_network(), params, &this->_association);
+ if(condition.bad())
+ {
+ OFString empty;
+
+ if(condition == DUL_ASSOCIATIONREJECTED)
+ {
+ T_ASC_RejectParameters rej;
+ ASC_getRejectParameters(params, &rej);
+
+ ASC_destroyAssociationParameters(¶ms);
+ throw Exception(ASC_printRejectParameters(empty, &rej).c_str());
+ }
+ else
+ {
+ ASC_destroyAssociationParameters(¶ms);
+ throw Exception(DimseCondition::dump(empty, condition).c_str());
+ }
+ }
+}
+
+void
+Association
+::receive(Network & network, bool accept_all)
+{
+ if(!network.is_initialized())
+ {
+ throw Exception("Network is not initialized");
+ }
+
+ if(this->is_associated())
+ {
+ throw Exception("Already associated");
+ }
+
+ OFCondition condition;
+
+ condition = ASC_receiveAssociation(
+ network.get_network(), &this->_association, ASC_DEFAULTMAXPDU);
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+
+ T_ASC_Parameters * const params = this->_association->params;
+ DUL_ASSOCIATESERVICEPARAMETERS const dul = params->DULparams;
+ // No peer port should be defined when receiving
+ this->_peer_host_name = dul.callingPresentationAddress;
+ this->_peer_port = 0;
+ this->_peer_ae_title = dul.callingAPTitle;
+
+ if(accept_all)
+ {
+ unsigned int const pc_count = ASC_countPresentationContexts(params);
+ for(unsigned int pc_index=0; pc_index<pc_count; ++pc_index)
+ {
+ T_ASC_PresentationContext pc;
+ memset(&pc, 0, sizeof(pc));
+ ASC_getPresentationContext(params, pc_index, &pc);
+
+ for(unsigned int ts_index=0; ts_index<pc.transferSyntaxCount; ++ts_index)
+ {
+ std::string const abstract_syntax = pc.abstractSyntax;
+ char const * abstract_syntax_data = abstract_syntax.c_str();
+
+ condition = ASC_acceptContextsWithTransferSyntax(
+ this->_association->params,
+ pc.proposedTransferSyntaxes[ts_index],
+ 1, &abstract_syntax_data);
+ if(condition.bad())
+ {
+ this->abort();
+ throw Exception(condition);
+ }
+ }
+ }
+ }
+ else
+ {
+ for(auto const & context: this->_presentation_contexts)
+ {
+ for(std::size_t i = 0; i < context.transfer_syntaxes.size(); ++i)
+ {
+ char const * abstract_syntax = context.abstract_syntax.c_str();
+ char const * transfer_syntax = context.transfer_syntaxes[i].c_str();
+ condition = ASC_acceptContextsWithTransferSyntax(
+ this->_association->params, transfer_syntax,
+ 1, &abstract_syntax);
+ if(condition.bad())
+ {
+ this->abort();
+ throw Exception(condition);
+ }
+ }
+ }
+ }
+
+ condition = ASC_acknowledgeAssociation(this->_association);
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+}
+
+T_ASC_Association *
+Association
+::get_association()
+{
+ return this->_association;
+}
+
+void
+Association
+::release()
+{
+ if(!this->is_associated())
+ {
+ throw Exception("Not associated");
+ }
+
+ ASC_releaseAssociation(this->_association);
+ ASC_destroyAssociation(&this->_association);
+ this->_association = NULL;
+}
+
+void
+Association
+::abort()
+{
+ if(!this->is_associated())
+ {
+ throw Exception("Not associated");
+ }
+
+ ASC_abortAssociation(this->_association);
+ ASC_destroyAssociation(&this->_association);
+ this->_association = NULL;
+}
+
+void
+Association
+::drop()
+{
+ if(!this->is_associated())
+ {
+ throw Exception("Not associated");
+ }
+
+ ASC_acknowledgeRelease(this->_association);
+ ASC_dropSCPAssociation(this->_association);
+ ASC_destroyAssociation(&this->_association);
+ this->_association = NULL;
+}
+
+}
diff --git a/src/dcmtkpp/Association.h b/src/dcmtkpp/Association.h
new file mode 100644
index 0000000..8b2fcb8
--- /dev/null
+++ b/src/dcmtkpp/Association.h
@@ -0,0 +1,184 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _a52696bc_5c6e_402d_a343_6cb085eb0138
+#define _a52696bc_5c6e_402d_a343_6cb085eb0138
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/assoc.h>
+
+#include "dcmtkpp/Network.h"
+
+namespace dcmtkpp
+{
+
+/// @brief User identity types as defined by PS3.8 2013 D.3.3.7
+enum class UserIdentityType
+{
+ None = 0,
+ Username = 1,
+ UsernameAndPassword = 2,
+ Kerberos = 3,
+ SAML = 4
+};
+
+/**
+ * @brief Wrapper around the T_ASC_Association class.
+ *
+ * No member can be set while the object is associated.
+ */
+class Association
+{
+public:
+ /// @brief Create a default, un-associated, association.
+ Association();
+
+ /// @brief Create an un-associated association.
+ Association(Association const & other);
+
+ /// @brief Destroy the association, release it if necessary.
+ ~Association();
+
+ /// @brief Assing an un-associated association; it remains un-associated.
+ Association & operator=(Association const & other);
+
+ /// @brief Return the AE title of the caller. Defaults to "".
+ std::string const & get_own_ae_title() const;
+ /// @brief Set the AE title of the caller.
+ void set_own_ae_title(std::string const & ae_title);
+
+ /// @name Peer
+ /// @{
+
+ /// @brief Return the host name of the peer. Defaults to "".
+ std::string const & get_peer_host_name() const;
+ /// @brief Set the host name of the peer.
+ void set_peer_host_name(std::string const & host_name);
+
+ /// @brief Return the port of the peer. Defaults to 104.
+ uint16_t get_peer_port() const;
+ /// @brief Set the port of the peer.
+ void set_peer_port(uint16_t port);
+
+ /// @brief Return the AE title of the peer. Defaults to "".
+ std::string const & get_peer_ae_title() const;
+ /// @brief Set the AE title of the peer.
+ void set_peer_ae_title(std::string const & ae_title);
+
+ /// @}
+
+ /// @name Presentation contexts
+ /// @{
+
+ void add_presentation_context(std::string const & abstract_syntax,
+ std::vector<std::string> const & transfer_syntaxes,
+ T_ASC_SC_ROLE role=ASC_SC_ROLE_DEFAULT);
+
+ /// @}
+
+ /// @name User identity
+ /// @{
+
+ /// @brief Return the user identity type. Defaults to None.
+ UserIdentityType get_user_identity_type() const;
+ /// @brief Set the user identity type.
+ void set_user_identity_type(UserIdentityType type);
+
+ /// @brief Return the user identity primary field. Defaults to "".
+ std::string const & get_user_identity_primary_field() const;
+ /// @brief Set the user identity primary field.
+ void set_user_identity_primary_field(std::string const & value);
+
+ /// @brief Return the user identity secondary field. Defaults to "".
+ std::string const & get_user_identity_secondary_field() const;
+ /// @brief Set the user identity secondary field.
+ void set_user_identity_secondary_field(std::string const & value);
+
+ /// @brief Do no authenticate user.
+ void set_user_identity_to_none();
+
+ /// @brief Authenticate user using only a username.
+ void set_user_identity_to_username(std::string const & username);
+
+ /// @brief Authenticate user using a username and a password.
+ void set_user_identity_to_username_and_password(
+ std::string const & username, std::string const & password);
+
+ /// @brief Authenticate user using a Kerberos ticket.
+ void set_user_identity_to_kerberos(std::string const & ticket);
+
+ /// @brief Authenticate user using a SAML assertion.
+ void set_user_identity_to_saml(std::string const & assertion);
+
+ /// @}
+
+ /// @name Association
+ /// @{
+
+ /// @brief Test whether the object is currently associated to its peer.
+ bool is_associated() const;
+
+ /**
+ * @brief Request an association with the peer.
+ * @param network network to use for the data transmission.
+ *
+ * Throws an exception if already associated.
+ */
+ void associate(Network & network);
+
+ /**
+ * @brief Receive an association for a peer.
+ * @param network network to use for the data transmission.
+ * @param accept_all if true, accept all presentations contexts proposed
+ * by peer.
+ */
+ void receive(Network & network, bool accept_all=false);
+
+ /// @brief Return the association object.
+ T_ASC_Association * get_association();
+
+ /// @brief Gracefully release the association. Throws an exception if not associated.
+ void release();
+ /// @brief Forcefully release the association. Throws an exception if not associated.
+ void abort();
+
+ /// @brief Drop an association that has been released by the peer.
+ void drop();
+
+ /// @}
+
+private:
+ std::string _own_ae_title;
+
+ std::string _peer_host_name;
+ uint16_t _peer_port;
+ std::string _peer_ae_title;
+
+ struct PresentationContext
+ {
+ std::string abstract_syntax;
+ std::vector<std::string> transfer_syntaxes;
+ T_ASC_SC_ROLE role;
+ };
+
+ std::vector<PresentationContext> _presentation_contexts;
+
+ UserIdentityType _user_identity_type;
+ std::string _user_identity_primary_field;
+ std::string _user_identity_secondary_field;
+
+ T_ASC_Association * _association;
+};
+
+}
+
+#endif // _a52696bc_5c6e_402d_a343_6cb085eb0138
diff --git a/src/dcmtkpp/CEchoRequest.cpp b/src/dcmtkpp/CEchoRequest.cpp
new file mode 100644
index 0000000..858abbb
--- /dev/null
+++ b/src/dcmtkpp/CEchoRequest.cpp
@@ -0,0 +1,47 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CEchoRequest.h"
+
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CEchoRequest
+::CEchoRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid)
+: Request(message_id)
+{
+ this->set_command_field(Command::C_ECHO_RQ);
+ this->set_affected_sop_class_uid(affected_sop_class_uid);
+}
+
+CEchoRequest
+::CEchoRequest(Message const & message)
+: Request(message)
+{
+ if(message.get_command_field() != Command::C_ECHO_RQ)
+ {
+ throw Exception("Message is not a C-ECHO-RQ");
+ }
+ this->set_command_field(message.get_command_field());
+
+ this->set_affected_sop_class_uid(
+ message.get_command_set().as_string(registry::AffectedSOPClassUID, 0));
+}
+
+CEchoRequest
+::~CEchoRequest()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CEchoRequest.h b/src/dcmtkpp/CEchoRequest.h
new file mode 100644
index 0000000..deb60a5
--- /dev/null
+++ b/src/dcmtkpp/CEchoRequest.h
@@ -0,0 +1,47 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _aec786b8_0074_4cb2_b9a1_4bf26bbd20fc
+#define _aec786b8_0074_4cb2_b9a1_4bf26bbd20fc
+
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-ECHO-RQ message.
+class CEchoRequest: public Request
+{
+public:
+ /**
+ * @brief Create an echo request with given Message ID and
+ * affected SOP class UID.
+ */
+ CEchoRequest(
+ Value::Integer message_id,
+ Value::String const & affected_sop_class_uid);
+
+ /**
+ * @brief Create a C-ECHO-RQ from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-ECHO-RQ.
+ */
+ CEchoRequest(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CEchoRequest();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+};
+
+}
+
+#endif // _aec786b8_0074_4cb2_b9a1_4bf26bbd20fc
diff --git a/src/dcmtkpp/CEchoResponse.cpp b/src/dcmtkpp/CEchoResponse.cpp
new file mode 100644
index 0000000..ec176b3
--- /dev/null
+++ b/src/dcmtkpp/CEchoResponse.cpp
@@ -0,0 +1,49 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CEchoResponse.h"
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CEchoResponse
+::CEchoResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status,
+ Value::String const & affected_sop_class_uid)
+: Response(message_id_being_responded_to, status)
+{
+ this->set_command_field(Command::C_ECHO_RSP);
+ this->set_affected_sop_class_uid(affected_sop_class_uid);
+}
+
+CEchoResponse
+::CEchoResponse(Message const & message)
+: Response(message)
+{
+ if(message.get_command_field() != Command::C_ECHO_RSP)
+ {
+ throw Exception("Message is not a C-ECHO-RSP");
+ }
+ this->set_command_field(message.get_command_field());
+
+ this->set_affected_sop_class_uid(
+ message.get_command_set().as_string(registry::AffectedSOPClassUID, 0));
+}
+
+CEchoResponse
+::~CEchoResponse()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CEchoResponse.h b/src/dcmtkpp/CEchoResponse.h
new file mode 100644
index 0000000..51c19d9
--- /dev/null
+++ b/src/dcmtkpp/CEchoResponse.h
@@ -0,0 +1,47 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _266252d9_e801_479e_a805_004b101c5250
+#define _266252d9_e801_479e_a805_004b101c5250
+
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-ECHO-RSP message.
+class CEchoResponse: public Response
+{
+public:
+ /**
+ * @brief Create an echo response with given Message ID and
+ * affected SOP class UID.
+ */
+ CEchoResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status,
+ Value::String const & affected_sop_class_uid);
+
+ /**
+ * @brief Create a C-ECHO-RSP from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-ECHO-RSP.
+ */
+ CEchoResponse(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CEchoResponse();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+};
+
+}
+
+#endif // _266252d9_e801_479e_a805_004b101c5250
diff --git a/src/dcmtkpp/CFindRequest.cpp b/src/dcmtkpp/CFindRequest.cpp
new file mode 100644
index 0000000..1c096c3
--- /dev/null
+++ b/src/dcmtkpp/CFindRequest.cpp
@@ -0,0 +1,65 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CFindRequest.h"
+
+#include <string>
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CFindRequest
+::CFindRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid,
+ Value::Integer priority, DataSet const & dataset)
+: Request(message_id)
+{
+ this->set_command_field(Command::C_FIND_RQ);
+ this->set_affected_sop_class_uid(affected_sop_class_uid);
+ this->set_priority(priority);
+ if(dataset.empty())
+ {
+ throw Exception("Data set is required");
+ }
+ this->set_data_set(dataset);
+}
+
+CFindRequest
+::CFindRequest(Message const & message)
+: Request(message)
+{
+ if(message.get_command_field() != Command::C_FIND_RQ)
+ {
+ throw Exception("Message is not a C-FIND-RQ");
+ }
+ this->set_command_field(message.get_command_field());
+
+ this->set_affected_sop_class_uid(
+ message.get_command_set().as_string(registry::AffectedSOPClassUID, 0));
+
+ this->set_priority(message.get_command_set().as_int(registry::Priority, 0));
+
+ if(!message.has_data_set() || message.get_data_set().empty())
+ {
+ throw Exception("Data set is required");
+ }
+ this->set_data_set(message.get_data_set());
+}
+
+CFindRequest
+::~CFindRequest()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CFindRequest.h b/src/dcmtkpp/CFindRequest.h
new file mode 100644
index 0000000..6b9e685
--- /dev/null
+++ b/src/dcmtkpp/CFindRequest.h
@@ -0,0 +1,48 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _74cfa9e7_da35_4130_a941_e17cb6932f60
+#define _74cfa9e7_da35_4130_a941_e17cb6932f60
+
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-FIND-RQ message.
+class CFindRequest: public Request
+{
+public:
+ /**
+ * @brief Create an find request with given Message ID,
+ * affected SOP class UID, priority, and data set.
+ */
+ CFindRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid,
+ Value::Integer priority, DataSet const & dataset);
+
+ /**
+ * @brief Create a C-FIND-RQ from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-FIND-RQ.
+ */
+ CFindRequest(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CFindRequest();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(priority, registry::Priority)
+};
+
+}
+
+#endif // _74cfa9e7_da35_4130_a941_e17cb6932f60
diff --git a/src/dcmtkpp/CFindResponse.cpp b/src/dcmtkpp/CFindResponse.cpp
new file mode 100644
index 0000000..a70d6d8
--- /dev/null
+++ b/src/dcmtkpp/CFindResponse.cpp
@@ -0,0 +1,66 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CFindResponse.h"
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CFindResponse
+::CFindResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status)
+: Response(message_id_being_responded_to, status)
+{
+ this->set_command_field(Command::C_FIND_RSP);
+}
+
+CFindResponse
+::CFindResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status,
+ DataSet const & dataset)
+: Response(message_id_being_responded_to, status)
+{
+ this->set_command_field(Command::C_FIND_RSP);
+ this->set_data_set(dataset);
+}
+
+CFindResponse
+::CFindResponse(Message const & message)
+: Response(message)
+{
+ if(message.get_command_field() != Command::C_FIND_RSP)
+ {
+ throw Exception("Message is not a C-FIND-RSP");
+ }
+ this->set_command_field(message.get_command_field());
+
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), message_id, registry::MessageID, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), affected_sop_class_uid,
+ registry::AffectedSOPClassUID, as_string)
+
+ if(message.has_data_set())
+ {
+ this->set_data_set(message.get_data_set());
+ }
+}
+
+CFindResponse
+::~CFindResponse()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CFindResponse.h b/src/dcmtkpp/CFindResponse.h
new file mode 100644
index 0000000..af44833
--- /dev/null
+++ b/src/dcmtkpp/CFindResponse.h
@@ -0,0 +1,55 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _5fd36547_9498_4cf3_87cc_737af51e93a9
+#define _5fd36547_9498_4cf3_87cc_737af51e93a9
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-FIND-RSP message.
+class CFindResponse: public Response
+{
+public:
+ /**
+ * @brief Create an find response with given Message ID, and status.
+ */
+ CFindResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status);
+
+ /**
+ * @brief Create an find response with given Message ID, status,
+ * and data set.
+ */
+ CFindResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status,
+ DataSet const & dataset);
+
+ /**
+ * @brief Create a C-FIND-RSP from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-FIND-RSP.
+ */
+ CFindResponse(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CFindResponse();
+
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(message_id, registry::MessageID)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+};
+
+}
+
+#endif // _5fd36547_9498_4cf3_87cc_737af51e93a9
diff --git a/src/dcmtkpp/CGetRequest.cpp b/src/dcmtkpp/CGetRequest.cpp
new file mode 100644
index 0000000..3a0d5a6
--- /dev/null
+++ b/src/dcmtkpp/CGetRequest.cpp
@@ -0,0 +1,66 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CGetRequest.h"
+
+#include <string>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CGetRequest
+::CGetRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid,
+ Value::Integer priority, DataSet const & dataset)
+: Request(message_id)
+{
+ this->set_command_field(Command::C_GET_RQ);
+ this->set_affected_sop_class_uid(affected_sop_class_uid);
+ this->set_priority(priority);
+ if(dataset.empty())
+ {
+ throw Exception("Data set is required");
+ }
+ this->set_data_set(dataset);
+}
+
+CGetRequest
+::CGetRequest(Message const & message)
+: Request(message)
+{
+ if(message.get_command_field() != Command::C_GET_RQ)
+ {
+ throw Exception("Message is not a C-GET-RQ");
+ }
+ this->set_command_field(message.get_command_field());
+
+ this->set_affected_sop_class_uid(
+ message.get_command_set().as_string(registry::AffectedSOPClassUID, 0));
+
+ this->set_priority(message.get_command_set().as_int(registry::Priority, 0));
+
+ if(!message.has_data_set() || message.get_data_set().empty())
+ {
+ throw Exception("Data set is required");
+ }
+ this->set_data_set(message.get_data_set());
+}
+
+CGetRequest
+::~CGetRequest()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CGetRequest.h b/src/dcmtkpp/CGetRequest.h
new file mode 100644
index 0000000..a9061b8
--- /dev/null
+++ b/src/dcmtkpp/CGetRequest.h
@@ -0,0 +1,49 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _6a22f126_7cc6_47ab_81c2_5f66b2714345
+#define _6a22f126_7cc6_47ab_81c2_5f66b2714345
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-GET-RQ message.
+class CGetRequest: public Request
+{
+public:
+ /**
+ * @brief Create an get request with given Message ID,
+ * affected SOP class UID, priority, and data set.
+ */
+ CGetRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid,
+ Value::Integer priority, DataSet const & dataset);
+
+ /**
+ * @brief Create a C-GET-RQ from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-GET-RQ.
+ */
+ CGetRequest(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CGetRequest();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(priority, registry::Priority)
+};
+
+}
+
+#endif // _6a22f126_7cc6_47ab_81c2_5f66b2714345
diff --git a/src/dcmtkpp/CGetResponse.cpp b/src/dcmtkpp/CGetResponse.cpp
new file mode 100644
index 0000000..3deda8f
--- /dev/null
+++ b/src/dcmtkpp/CGetResponse.cpp
@@ -0,0 +1,79 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CGetResponse.h"
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CGetResponse
+::CGetResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status)
+: Response(message_id_being_responded_to, status)
+{
+ this->set_command_field(Command::C_GET_RSP);
+}
+
+CGetResponse
+::CGetResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status,
+ DataSet const & dataset)
+: Response(message_id_being_responded_to, status)
+{
+ this->set_command_field(Command::C_GET_RSP);
+ this->set_data_set(dataset);
+}
+
+CGetResponse
+::CGetResponse(Message const & message)
+: Response(message)
+{
+ if(message.get_command_field() != Command::C_GET_RSP)
+ {
+ throw Exception("Message is not a C-GET-RSP");
+ }
+ this->set_command_field(message.get_command_field());
+
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), message_id, registry::MessageID, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), affected_sop_class_uid,
+ registry::AffectedSOPClassUID, as_string)
+
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), number_of_remaining_sub_operations,
+ registry::NumberOfRemainingSuboperations, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), number_of_completed_sub_operations,
+ registry::NumberOfCompletedSuboperations, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), number_of_failed_sub_operations,
+ registry::NumberOfFailedSuboperations, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), number_of_warning_sub_operations,
+ registry::NumberOfWarningSuboperations, as_int)
+
+ if(message.has_data_set())
+ {
+ this->set_data_set(message.get_data_set());
+ }
+}
+
+CGetResponse
+::~CGetResponse()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CGetResponse.h b/src/dcmtkpp/CGetResponse.h
new file mode 100644
index 0000000..d51cba1
--- /dev/null
+++ b/src/dcmtkpp/CGetResponse.h
@@ -0,0 +1,64 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _7b9819f1_d7a2_4898_a850_3ed6a61f08c6
+#define _7b9819f1_d7a2_4898_a850_3ed6a61f08c6
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-GET-RSP message.
+class CGetResponse: public Response
+{
+public:
+ /**
+ * @brief Create an get response with given Message ID, and status.
+ */
+ CGetResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status);
+
+ /**
+ * @brief Create an get response with given Message ID, status,
+ * and data set.
+ */
+ CGetResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status,
+ DataSet const & dataset);
+
+ /**
+ * @brief Create a C-GET-RSP from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-GET-RSP.
+ */
+ CGetResponse(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CGetResponse();
+
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(message_id, registry::MessageID)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ number_of_remaining_sub_operations, registry::NumberOfRemainingSuboperations)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ number_of_completed_sub_operations, registry::NumberOfCompletedSuboperations)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ number_of_failed_sub_operations, registry::NumberOfFailedSuboperations)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ number_of_warning_sub_operations, registry::NumberOfWarningSuboperations)
+};
+
+}
+
+#endif // _7b9819f1_d7a2_4898_a850_3ed6a61f08c6
diff --git a/src/dcmtkpp/CMoveRequest.cpp b/src/dcmtkpp/CMoveRequest.cpp
new file mode 100644
index 0000000..df21f83
--- /dev/null
+++ b/src/dcmtkpp/CMoveRequest.cpp
@@ -0,0 +1,69 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CMoveRequest.h"
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CMoveRequest
+::CMoveRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid,
+ Value::Integer priority, Value::String const & move_destination,
+ DataSet const & dataset)
+: Request(message_id)
+{
+ this->set_command_field(Command::C_MOVE_RQ);
+ this->set_affected_sop_class_uid(affected_sop_class_uid);
+ this->set_priority(priority);
+ this->set_move_destination(move_destination);
+ if(dataset.empty())
+ {
+ throw Exception("Data set is required");
+ }
+ this->set_data_set(dataset);
+}
+
+CMoveRequest
+::CMoveRequest(Message const & message)
+: Request(message)
+{
+ if(message.get_command_field() != Command::C_MOVE_RQ)
+ {
+ throw Exception("Message is not a C-MOVE-RQ");
+ }
+ this->set_command_field(message.get_command_field());
+
+ this->set_affected_sop_class_uid(
+ message.get_command_set().as_string(registry::AffectedSOPClassUID, 0));
+
+ this->set_priority(message.get_command_set().as_int(registry::Priority, 0));
+
+ this->set_move_destination(
+ message.get_command_set().as_string(registry::MoveDestination, 0));
+
+ if(!message.has_data_set() || message.get_data_set().empty())
+ {
+ throw Exception("Data set is required");
+ }
+ this->set_data_set(message.get_data_set());
+}
+
+CMoveRequest
+::~CMoveRequest()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CMoveRequest.h b/src/dcmtkpp/CMoveRequest.h
new file mode 100644
index 0000000..099e1f1
--- /dev/null
+++ b/src/dcmtkpp/CMoveRequest.h
@@ -0,0 +1,52 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _f6e243d2_6113_4fe3_8d04_3f034fc796bf
+#define _f6e243d2_6113_4fe3_8d04_3f034fc796bf
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-MOVE-RQ message.
+class CMoveRequest: public Request
+{
+public:
+ /**
+ * @brief Create an move request with given Message ID,
+ * affected SOP class UID, priority, move destination, and data set.
+ */
+ CMoveRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid,
+ Value::Integer priority, Value::String const & move_destination,
+ DataSet const & dataset);
+
+ /**
+ * @brief Create a C-MOVE-RQ from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-MOVE-RQ.
+ */
+ CMoveRequest(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CMoveRequest();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(priority, registry::Priority)
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(
+ move_destination, registry::MoveDestination)
+};
+
+}
+
+#endif // _f6e243d2_6113_4fe3_8d04_3f034fc796bf
diff --git a/src/dcmtkpp/CMoveResponse.cpp b/src/dcmtkpp/CMoveResponse.cpp
new file mode 100644
index 0000000..b1d70b6
--- /dev/null
+++ b/src/dcmtkpp/CMoveResponse.cpp
@@ -0,0 +1,79 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CMoveResponse.h"
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CMoveResponse
+::CMoveResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status)
+: Response(message_id_being_responded_to, status)
+{
+ this->set_command_field(Command::C_MOVE_RSP);
+}
+
+CMoveResponse
+::CMoveResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status,
+ DataSet const & dataset)
+: Response(message_id_being_responded_to, status)
+{
+ this->set_command_field(Command::C_MOVE_RSP);
+ this->set_data_set(dataset);
+}
+
+CMoveResponse
+::CMoveResponse(Message const & message)
+: Response(message)
+{
+ if(message.get_command_field() != Command::C_MOVE_RSP)
+ {
+ throw Exception("Message is not a C-MOVE-RSP");
+ }
+ this->set_command_field(message.get_command_field());
+
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), message_id, registry::MessageID, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), affected_sop_class_uid,
+ registry::AffectedSOPClassUID, as_string)
+
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), number_of_remaining_sub_operations,
+ registry::NumberOfRemainingSuboperations, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), number_of_completed_sub_operations,
+ registry::NumberOfCompletedSuboperations, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), number_of_failed_sub_operations,
+ registry::NumberOfFailedSuboperations, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), number_of_warning_sub_operations,
+ registry::NumberOfWarningSuboperations, as_int)
+
+ if(message.has_data_set())
+ {
+ this->set_data_set(message.get_data_set());
+ }
+}
+
+CMoveResponse
+::~CMoveResponse()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CMoveResponse.h b/src/dcmtkpp/CMoveResponse.h
new file mode 100644
index 0000000..21a5f48
--- /dev/null
+++ b/src/dcmtkpp/CMoveResponse.h
@@ -0,0 +1,64 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _b245f6f2_50c3_4c7c_80e1_f03d9c831301
+#define _b245f6f2_50c3_4c7c_80e1_f03d9c831301
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-MOVE-RSP message.
+class CMoveResponse: public Response
+{
+public:
+ /**
+ * @brief Create an move response with given Message ID, and status.
+ */
+ CMoveResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status);
+
+ /**
+ * @brief Create an move response with given Message ID, status,
+ * and data set.
+ */
+ CMoveResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status,
+ DataSet const & dataset);
+
+ /**
+ * @brief Create a C-MOVE-RSP from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-MOVE-RSP.
+ */
+ CMoveResponse(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CMoveResponse();
+
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(message_id, registry::MessageID)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ number_of_remaining_sub_operations, registry::NumberOfRemainingSuboperations)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ number_of_completed_sub_operations, registry::NumberOfCompletedSuboperations)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ number_of_failed_sub_operations, registry::NumberOfFailedSuboperations)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ number_of_warning_sub_operations, registry::NumberOfWarningSuboperations)
+};
+
+}
+
+#endif // _b245f6f2_50c3_4c7c_80e1_f03d9c831301
diff --git a/src/dcmtkpp/CStoreRequest.cpp b/src/dcmtkpp/CStoreRequest.cpp
new file mode 100644
index 0000000..1627fc7
--- /dev/null
+++ b/src/dcmtkpp/CStoreRequest.cpp
@@ -0,0 +1,75 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CStoreRequest.h"
+
+#include <string>
+
+#include "dcmtkpp/ElementAccessor.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Request.h"
+
+namespace dcmtkpp
+{
+
+CStoreRequest
+::CStoreRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid,
+ Value::String const & affected_sop_instance_uid,
+ Value::Integer priority, DataSet const & dataset)
+: Request(message_id)
+{
+ this->set_command_field(Command::C_STORE_RQ);
+ this->set_affected_sop_class_uid(affected_sop_class_uid);
+ this->set_affected_sop_instance_uid(affected_sop_instance_uid);
+ this->set_priority(priority);
+
+ if(dataset.empty())
+ {
+ throw Exception("Data set is required");
+ }
+ this->set_data_set(dataset);
+}
+
+CStoreRequest
+::CStoreRequest(Message const & message)
+: Request(message)
+{
+ if(message.get_command_field() != Command::C_STORE_RQ)
+ {
+ throw Exception("Message is not a C-STORE-RQ");
+ }
+ this->set_command_field(message.get_command_field());
+
+ this->set_affected_sop_class_uid(
+ message.get_command_set().as_string(registry::AffectedSOPClassUID, 0));
+ this->set_affected_sop_instance_uid(
+ message.get_command_set().as_string(registry::AffectedSOPInstanceUID, 0));
+ this->set_priority(message.get_command_set().as_int(registry::Priority, 0));
+
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), move_originator_ae_title,
+ registry::MoveOriginatorApplicationEntityTitle, as_string)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), move_originator_message_id,
+ registry::MoveOriginatorMessageID, as_int)
+
+ if(!message.has_data_set() || message.get_data_set().empty())
+ {
+ throw Exception("Data set is required");
+ }
+ this->set_data_set(message.get_data_set());
+}
+
+CStoreRequest
+::~CStoreRequest()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CStoreRequest.h b/src/dcmtkpp/CStoreRequest.h
new file mode 100644
index 0000000..169e126
--- /dev/null
+++ b/src/dcmtkpp/CStoreRequest.h
@@ -0,0 +1,61 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _b85a19af_b74d_4c96_89a0_f30a41b790b3
+#define _b85a19af_b74d_4c96_89a0_f30a41b790b3
+
+#include <string>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/ofstd/oftypes.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Request.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-STORE-RQ message.
+class CStoreRequest: public Request
+{
+public:
+ /**
+ * @brief Create an store request with given Message ID,
+ * affected SOP class UID, priority, and data set.
+ */
+ CStoreRequest(
+ Value::Integer message_id, Value::String const & affected_sop_class_uid,
+ Value::String const & affected_sop_instance_uid,
+ Value::Integer priority, DataSet const & dataset);
+
+ /**
+ * @brief Create a C-STORE-RQ from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-STORE-RQ.
+ */
+ CStoreRequest(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CStoreRequest();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(
+ affected_sop_instance_uid, registry::AffectedSOPInstanceUID)
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(priority, registry::Priority)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_STRING_MACRO(
+ move_originator_ae_title, registry::MoveOriginatorApplicationEntityTitle)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(
+ move_originator_message_id, registry::MoveOriginatorMessageID)
+};
+
+}
+
+#endif // _b85a19af_b74d_4c96_89a0_f30a41b790b3
diff --git a/src/dcmtkpp/CStoreResponse.cpp b/src/dcmtkpp/CStoreResponse.cpp
new file mode 100644
index 0000000..1c3a4b7
--- /dev/null
+++ b/src/dcmtkpp/CStoreResponse.cpp
@@ -0,0 +1,59 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "CStoreResponse.h"
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+CStoreResponse
+::CStoreResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status)
+: Response(message_id_being_responded_to, status)
+{
+ this->set_command_field(Command::C_STORE_RSP);
+}
+
+CStoreResponse
+::CStoreResponse(Message const & message)
+: Response(message)
+{
+ if(message.get_command_field() != Command::C_STORE_RSP)
+ {
+ throw Exception("Message is not a C-STORE-RSP");
+ }
+ this->set_command_field(message.get_command_field());
+
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), message_id, registry::MessageID, as_int)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(), affected_sop_class_uid,
+ registry::AffectedSOPClassUID, as_string)
+ DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(
+ message.get_command_set(),
+ affected_sop_instance_uid, registry::AffectedSOPInstanceUID, as_string)
+
+ if(message.has_data_set() && !message.get_data_set().empty())
+ {
+ throw Exception("Data set must not be present");
+ }
+ this->delete_data_set();
+}
+
+CStoreResponse
+::~CStoreResponse()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/CStoreResponse.h b/src/dcmtkpp/CStoreResponse.h
new file mode 100644
index 0000000..0565073
--- /dev/null
+++ b/src/dcmtkpp/CStoreResponse.h
@@ -0,0 +1,48 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _7e193624_081c_47dd_a011_986e96916ea9
+#define _7e193624_081c_47dd_a011_986e96916ea9
+
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Response.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief C-STORE-RSP message.
+class CStoreResponse: public Response
+{
+public:
+ /**
+ * @brief Create an store response with given Message ID, and status.
+ */
+ CStoreResponse(
+ Value::Integer message_id_being_responded_to, Value::Integer status);
+
+ /**
+ * @brief Create a C-STORE-RSP from a generic Message.
+ *
+ * Raise an exception if the Message does not contain a C-STORE-RSP.
+ */
+ CStoreResponse(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~CStoreResponse();
+
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(message_id, registry::MessageID)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_STRING_MACRO(
+ affected_sop_class_uid, registry::AffectedSOPClassUID)
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_STRING_MACRO(
+ affected_sop_instance_uid, registry::AffectedSOPInstanceUID)
+};
+
+}
+
+#endif // _7e193624_081c_47dd_a011_986e96916ea9
diff --git a/src/dcmtkpp/Cancellation.cpp b/src/dcmtkpp/Cancellation.cpp
new file mode 100644
index 0000000..af23345
--- /dev/null
+++ b/src/dcmtkpp/Cancellation.cpp
@@ -0,0 +1,46 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/Cancellation.h"
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+Cancellation
+::Cancellation(Uint16 message_id_being_responded_to)
+: Message()
+{
+ this->set_command_field(Command::C_CANCEL_RQ);
+ this->set_message_id_being_responded_to(message_id_being_responded_to);
+}
+
+Cancellation
+::Cancellation(Message const & message)
+{
+ if(message.get_command_field() != Command::C_CANCEL_RQ)
+ {
+ throw Exception("Message is not a C-CANCEL-RQ");
+ }
+ this->set_command_field(message.get_command_field());
+
+ this->set_message_id_being_responded_to(
+ message.get_command_set().as_int(registry::MessageIDBeingRespondedTo, 0));
+}
+
+Cancellation
+::~Cancellation()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/Cancellation.h b/src/dcmtkpp/Cancellation.h
new file mode 100644
index 0000000..d34d4f9
--- /dev/null
+++ b/src/dcmtkpp/Cancellation.h
@@ -0,0 +1,42 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _97fc1bfc_4cff_40f2_a1ed_4550c71a0bda
+#define _97fc1bfc_4cff_40f2_a1ed_4550c71a0bda
+
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Base class for cancellation messages.
+class Cancellation: public Message
+{
+public:
+ /// @brief Create a response with given message id being responded to.
+ Cancellation(Uint16 message_id_being_responded_to);
+
+ /**
+ * @brief Create a response from the Message ID Being Responded To.
+ *
+ * Raise an exception is this element is missing.
+ */
+ Cancellation(Message const & message);
+
+ /// @brief Destructor.
+ ~Cancellation();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(
+ message_id_being_responded_to, registry::MessageIDBeingRespondedTo);
+};
+
+}
+
+#endif // _97fc1bfc_4cff_40f2_a1ed_4550c71a0bda
diff --git a/src/dcmtkpp/DataSet.cpp b/src/dcmtkpp/DataSet.cpp
new file mode 100644
index 0000000..120462e
--- /dev/null
+++ b/src/dcmtkpp/DataSet.cpp
@@ -0,0 +1,308 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/DataSet.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <map>
+#include <string>
+#include <vector>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcdicent.h>
+#include <dcmtk/dcmdata/dcdict.h>
+#include <dcmtk/dcmdata/dctagkey.h>
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Tag.h"
+#include "dcmtkpp/VR.h"
+
+namespace dcmtkpp
+{
+
+DataSet
+::DataSet()
+{
+ // Nothing to do.
+}
+
+void
+DataSet
+::add(Tag const & tag, Element const & element)
+{
+ this->_elements[tag] = element;
+}
+
+
+void
+DataSet
+::add(Tag const & tag, VR vr)
+{
+ Value value;
+
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+
+ if(::dcmtkpp::is_int(vr))
+ {
+ value = Value::Integers();
+ }
+ else if(::dcmtkpp::is_real(vr))
+ {
+ value = Value::Reals();
+ }
+ else if(::dcmtkpp::is_string(vr))
+ {
+ value = Value::Strings();
+ }
+ else if(::dcmtkpp::is_binary(vr))
+ {
+ value = Value::Binary();
+ }
+ else if(vr == VR::SQ)
+ {
+ value = Value::DataSets();
+ }
+ else
+ {
+ throw Exception("Unknown VR: "+::dcmtkpp::as_string(vr));
+ }
+
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(Tag const & tag, Value::Integers const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(Tag const & tag, Value::Reals const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(Tag const & tag, Value::Strings const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(Tag const & tag, Value::DataSets const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(Tag const & tag, Value::Binary const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(Tag const & tag, std::initializer_list<int> const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(
+ Tag const & tag, std::initializer_list<Value::Integer> const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(
+ Tag const & tag, std::initializer_list<Value::Real> const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(
+ Tag const & tag, std::initializer_list<Value::String> const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::add(
+ Tag const & tag, std::initializer_list<DataSet> const & value, VR vr)
+{
+ if(vr == VR::UNKNOWN)
+ {
+ vr = as_vr(tag);
+ }
+ this->add(tag, Element(value, vr));
+}
+
+void
+DataSet
+::remove(Tag const & tag)
+{
+ if(!this->has(tag))
+ {
+ throw Exception("No such element");
+ }
+
+ this->_elements.erase(tag);
+}
+
+bool
+DataSet
+::empty() const
+{
+ return this->_elements.empty();
+}
+
+std::size_t
+DataSet
+::size() const
+{
+ return this->_elements.size();
+}
+
+Element const &
+DataSet
+::operator[](Tag const & tag) const
+{
+ ElementMap::const_iterator const it = this->_elements.find(tag);
+ if(it == this->_elements.end())
+ {
+ throw Exception("No such element");
+ }
+
+ return it->second;
+}
+
+Element &
+DataSet
+::operator[](Tag const & tag)
+{
+ ElementMap::iterator it = this->_elements.find(tag);
+ if(it == this->_elements.end())
+ {
+ throw Exception("No such element");
+ }
+
+ return it->second;
+}
+
+bool
+DataSet
+::has(Tag const & tag) const
+{
+ return (this->_elements.find(tag) != this->_elements.end());
+}
+
+VR
+DataSet
+::get_vr(Tag const & tag) const
+{
+ ElementMap::const_iterator const it = this->_elements.find(tag);
+ if(it == this->_elements.end())
+ {
+ throw Exception("No such element");
+ }
+
+ return it->second.vr;
+}
+
+bool
+DataSet
+::empty(Tag const & tag) const
+{
+ ElementMap::const_iterator const it = this->_elements.find(tag);
+ if(it == this->_elements.end())
+ {
+ throw Exception("No such element");
+ }
+
+ return it->second.empty();
+}
+
+std::size_t
+DataSet
+::size(Tag const & tag) const
+{
+ ElementMap::const_iterator const it = this->_elements.find(tag);
+ if(it == this->_elements.end())
+ {
+ throw Exception("No such element");
+ }
+
+ return it->second.size();
+}
+
+bool
+DataSet
+::operator==(DataSet const & other) const
+{
+ return (this->_elements == other._elements);
+}
+
+bool
+DataSet
+::operator!=(DataSet const & other) const
+{
+ return !(*this == other);
+}
+
+}
diff --git a/src/dcmtkpp/DataSet.h b/src/dcmtkpp/DataSet.h
new file mode 100644
index 0000000..2114f86
--- /dev/null
+++ b/src/dcmtkpp/DataSet.h
@@ -0,0 +1,200 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _8424446e_1153_4acc_9f57_e86faa7246e3
+#define _8424446e_1153_4acc_9f57_e86faa7246e3
+
+#include <cstddef>
+#include <cstdint>
+#include <initializer_list>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "dcmtkpp/Element.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+#define dcmtkppElementTypeMacro(name, Type) \
+bool is_##name(Tag const & tag) const \
+{ \
+ auto const it = this->_elements.find(tag); \
+ if(it == this->_elements.end()) \
+ { \
+ throw Exception("No such element"); \
+ } \
+ return it->second.is_##name(); \
+} \
+Value::Type const & as_##name(Tag const & tag) const \
+{ \
+ auto const it = this->_elements.find(tag); \
+ if(it == this->_elements.end()) \
+ { \
+ throw Exception("No such element"); \
+ } \
+ return it->second.as_##name(); \
+} \
+Value::Type::value_type const & as_##name(Tag const & tag, int position) const \
+{ \
+ auto const & data = this->as_##name(tag); \
+ if(data.size() <= position) \
+ { \
+ throw Exception("No such element"); \
+ } \
+ return data[position]; \
+} \
+Value::Type & as_##name(Tag const & tag) \
+{ \
+ auto const it = this->_elements.find(tag); \
+ if(it == this->_elements.end()) \
+ { \
+ throw Exception("No such element"); \
+ } \
+ return it->second.as_##name(); \
+}
+
+/**
+ * @brief DICOM Data set.
+ */
+class DataSet
+{
+public:
+ /// @brief Create an empty data set.
+ DataSet();
+
+ /// @brief Add an element to the dataset.
+ void add(Tag const & tag, Element const & element);
+
+ /// @brief Add an empty element to the dataset.
+ void add(Tag const & tag, VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, Value::Integers const & value, VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, Value::Reals const & value, VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, Value::Strings const & value, VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, Value::DataSets const & value, VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, Value::Binary const & value, VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, std::initializer_list<int> const & value,
+ VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, std::initializer_list<Value::Integer> const & value,
+ VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, std::initializer_list<Value::Real> const & value,
+ VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, std::initializer_list<Value::String> const & value,
+ VR vr=VR::UNKNOWN);
+
+ /// @brief Add an element to the dataset.
+ void add(
+ Tag const & tag, std::initializer_list<DataSet> const & value,
+ VR vr=VR::UNKNOWN);
+
+ /**
+ * @brief Remove an element from the data set.
+ *
+ * If the element is not in the data set, a dcmtkpp::Exception is raised.
+ */
+ void remove(Tag const & tag);
+
+ /// @brief Test whether the data set is empty.
+ bool empty() const;
+
+ /// @brief Return the number of elements in the data set.
+ std::size_t size() const;
+
+ /// @brief Test whether an element is in the data set.
+ bool has(Tag const & tag) const;
+
+ /**
+ * @brief Return the VR of an element in the data set.
+ *
+ * If the element is not in the data set, a dcmtkpp::Exception is raised.
+ */
+ VR get_vr(Tag const & tag) const;
+
+ /**
+ * @brief Test whether an element of the data set is empty.
+ *
+ * If the element is not in the data set, a dcmtkpp::Exception is raised.
+ */
+ bool empty(Tag const & tag) const;
+
+ /**
+ * @brief Return the number of values in an element of the data set.
+ *
+ * If the element is not in the data set, a dcmtkpp::Exception is raised.
+ */
+ std::size_t size(Tag const & tag) const;
+
+ /**
+ * @brief Access the given element.
+ *
+ * If the element is not in the data set, a dcmtkpp::Exception is raised.
+ */
+ Element const & operator[](Tag const & tag) const;
+
+ /**
+ * @brief Access the given element.
+ *
+ * If the element is not in the data set, a dcmtkpp::Exception is raised.
+ */
+ Element & operator[](Tag const & tag);
+
+ dcmtkppElementTypeMacro(int, Integers);
+ dcmtkppElementTypeMacro(real, Reals);
+ dcmtkppElementTypeMacro(string, Strings);
+ dcmtkppElementTypeMacro(data_set, DataSets);
+ dcmtkppElementTypeMacro(binary, Binary);
+
+ typedef std::map<Tag, Element>::const_iterator const_iterator;
+ const_iterator begin() const { return this->_elements.begin(); }
+ const_iterator end() const { return this->_elements.end(); }
+
+ // FIXME: AT, binary
+
+ /// @brief Equality test
+ bool operator==(DataSet const & other) const;
+
+ /// @brief Difference test
+ bool operator!=(DataSet const & other) const;
+
+private:
+ typedef std::map<Tag, Element> ElementMap;
+
+ ElementMap _elements;
+};
+
+}
+
+#endif // _8424446e_1153_4acc_9f57_e86faa7246e3
diff --git a/src/dcmtkpp/Element.cpp b/src/dcmtkpp/Element.cpp
new file mode 100644
index 0000000..ab58fd7
--- /dev/null
+++ b/src/dcmtkpp/Element.cpp
@@ -0,0 +1,236 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/Element.h"
+
+#include "dcmtkpp/Value.h"
+#include "dcmtkpp/DataSet.h"
+
+namespace dcmtkpp
+{
+
+Element
+::Element(Value const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(Value::Integers const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(Value::Reals const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(Value::Strings const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(Value::DataSets const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(Value::Binary const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(std::initializer_list<int> const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(std::initializer_list<Value::Integer> const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(std::initializer_list<Value::Real> const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(std::initializer_list<Value::String> const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+Element
+::Element(std::initializer_list<DataSet> const & value, VR const & vr)
+: _value(value), vr(vr)
+{
+ // Nothing else
+}
+
+bool
+Element
+::empty() const
+{
+ return (
+ (this->_value.get_type() == Value::Type::Empty) ||
+ apply_visitor(Empty(), this->_value));
+}
+
+std::size_t
+Element
+::size() const
+{
+ return (
+ (this->_value.get_type() == Value::Type::Empty)?0:
+ apply_visitor(Size(), this->_value));
+}
+
+Value const &
+Element
+::get_value() const
+{
+ return this->_value;
+}
+
+bool
+Element
+::is_int() const
+{
+ return (this->_value.get_type() == Value::Type::Integers);
+}
+
+Value::Integers const &
+Element
+::as_int() const
+{
+ return this->_value.as_integers();
+}
+
+Value::Integers &
+Element
+::as_int()
+{
+ return this->_value.as_integers();
+}
+
+bool
+Element
+::is_real() const
+{
+ return (this->_value.get_type() == Value::Type::Reals);
+}
+
+Value::Reals const &
+Element
+::as_real() const
+{
+ return this->_value.as_reals();
+}
+
+Value::Reals &
+Element
+::as_real()
+{
+ return this->_value.as_reals();
+}
+
+bool
+Element
+::is_string() const
+{
+ return (this->_value.get_type() == Value::Type::Strings);
+}
+
+Value::Strings const &
+Element
+::as_string() const
+{
+ return this->_value.as_strings();
+}
+
+Value::Strings &
+Element
+::as_string()
+{
+ return this->_value.as_strings();
+}
+
+bool
+Element
+::is_data_set() const
+{
+ return (this->_value.get_type() == Value::Type::DataSets);
+}
+
+Value::DataSets const &
+Element
+::as_data_set() const
+{
+ return this->_value.as_data_sets();
+}
+
+Value::DataSets &
+Element::as_data_set()
+{
+ return this->_value.as_data_sets();
+}
+
+bool
+Element
+::is_binary() const
+{
+ return (this->_value.get_type() == Value::Type::Binary);
+}
+
+Value::Binary const &
+Element
+::as_binary() const
+{
+ return this->_value.as_binary();
+}
+
+Value::Binary &
+Element::as_binary()
+{
+ return this->_value.as_binary();
+}
+
+bool
+Element
+::operator==(Element const & other) const
+{
+ return (this->vr == other.vr) && (this->_value == other._value);
+}
+
+bool
+Element
+::operator!=(Element const & other) const
+{
+ return !(*this == other);
+}
+
+}
diff --git a/src/dcmtkpp/Element.h b/src/dcmtkpp/Element.h
new file mode 100644
index 0000000..9959c3b
--- /dev/null
+++ b/src/dcmtkpp/Element.h
@@ -0,0 +1,212 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _9c3d8f32_0310_4e3a_b5d2_6d69f229a2cf
+#define _9c3d8f32_0310_4e3a_b5d2_6d69f229a2cf
+
+#include <cstddef>
+#include <initializer_list>
+
+#include "dcmtkpp/Tag.h"
+#include "dcmtkpp/Value.h"
+#include "dcmtkpp/VR.h"
+
+namespace dcmtkpp
+{
+
+/**
+ * @brief Element of a DICOM data set.
+ */
+class Element
+{
+public:
+
+ /// @brief VR of the element.
+ VR vr;
+
+ /// @brief Constructor.
+ Element(Value const & value=Value(), VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(Value::Integers const & value, VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(Value::Reals const & value, VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(Value::Strings const & value, VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(Value::DataSets const & value, VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(Value::Binary const & value, VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(
+ std::initializer_list<int> const & value, VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(
+ std::initializer_list<Value::Integer> const & value,
+ VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(
+ std::initializer_list<Value::Real> const & value,
+ VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(
+ std::initializer_list<Value::String> const & value,
+ VR const & vr=VR::INVALID);
+
+ /// @brief Constructor.
+ Element(
+ std::initializer_list<DataSet> const & value,
+ VR const & vr=VR::INVALID);
+
+ /// @brief Test whether the element is empty.
+ bool empty() const;
+
+ /// @brief Return the number of items in the value.
+ std::size_t size() const;
+
+ Value const & get_value() const;
+
+ /// @brief Test whether the value contains integers.
+ bool is_int() const;
+
+ /**
+ * @brief Return the integers contained in the element.
+ *
+ * If the element does not contain integers, a dcmtkpp::Exception is raised.
+ */
+ Value::Integers const & as_int() const;
+
+ /**
+ * @brief Return the integers contained in the element.
+ *
+ * If the element does not contain integers, a dcmtkpp::Exception is raised.
+ */
+ Value::Integers & as_int();
+
+ /// @brief Test whether the value contains reals.
+ bool is_real() const;
+
+ /**
+ * @brief Return the reals contained in the element.
+ *
+ * If the element does not contain reals, a dcmtkpp::Exception is raised.
+ */
+ Value::Reals const & as_real() const;
+
+ /**
+ * @brief Return the reals contained in the element.
+ *
+ * If the element does not contain reals, a dcmtkpp::Exception is raised.
+ */
+ Value::Reals & as_real();
+
+ /// @brief Test whether the value contains strings.
+ bool is_string() const;
+
+ /**
+ * @brief Return the strings contained in the element.
+ *
+ * If the element does not contain strings, a dcmtkpp::Exception is raised.
+ */
+ Value::Strings const & as_string() const;
+
+ /**
+ * @brief Return the strings contained in the element.
+ *
+ * If the element does not contain strings, a dcmtkpp::Exception is raised.
+ */
+ Value::Strings & as_string();
+
+ /// @brief Test whether the value contains data sets.
+ bool is_data_set() const;
+
+ /**
+ * @brief Return the data sets contained in the element.
+ *
+ * If the element does not contain data sets, a dcmtkpp::Exception is raised.
+ */
+ Value::DataSets const & as_data_set() const;
+
+ /**
+ * @brief Return the data sets contained in the element.
+ *
+ * If the element does not contain data sets, a dcmtkpp::Exception is raised.
+ */
+ Value::DataSets & as_data_set();
+
+ /// @brief Test whether the value contains data sets.
+ bool is_binary() const;
+
+ /**
+ * @brief Return the binary data contained in the element.
+ *
+ * If the element does not contain binary data, a dcmtkpp::Exception is raised.
+ */
+ Value::Binary const & as_binary() const;
+
+ /**
+ * @brief Return the binary data contained in the element.
+ *
+ * If the element does not contain binary data, a dcmtkpp::Exception is raised.
+ */
+ Value::Binary & as_binary();
+
+ /// @brief Equality test
+ bool operator==(Element const & other) const;
+
+ /// @brief Difference test
+ bool operator!=(Element const & other) const;
+
+private:
+ struct Empty
+ {
+ typedef bool result_type;
+
+ template<typename T>
+ bool operator()(T const & container) const
+ {
+ return container.empty();
+ }
+ };
+
+ struct Size
+ {
+ typedef std::size_t result_type;
+
+ template<typename T>
+ std::size_t operator()(T const & container) const
+ {
+ return container.size();
+ }
+ };
+
+
+ Value _value;
+};
+
+/**
+ * @brief Visitor of elements.
+ */
+template<typename TVisitor>
+typename TVisitor::result_type
+apply_visitor(TVisitor const & visitor, Element const & element);
+
+
+}
+
+#include "dcmtkpp/Element.txx"
+
+#endif // _9c3d8f32_0310_4e3a_b5d2_6d69f229a2cf
diff --git a/src/dcmtkpp/Element.txx b/src/dcmtkpp/Element.txx
new file mode 100644
index 0000000..2ec2f54
--- /dev/null
+++ b/src/dcmtkpp/Element.txx
@@ -0,0 +1,57 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _feb2071a_de26_4adb_9305_59d0dd64c970
+#define _feb2071a_de26_4adb_9305_59d0dd64c970
+
+#include "dcmtkpp/Element.h"
+
+#include <vector>
+
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+template<typename TVisitor>
+typename TVisitor::result_type
+apply_visitor(TVisitor const & visitor, Element const & element)
+{
+ if(element.empty())
+ {
+ return visitor(element.vr);
+ }
+ else if(is_string(element.vr))
+ {
+ return visitor(element.vr, element.as_string());
+ }
+ else if(is_real(element.vr))
+ {
+ return visitor(element.vr, element.as_real());
+ }
+ else if(is_int(element.vr))
+ {
+ return visitor(element.vr, element.as_int());
+ }
+ else if(element.vr == VR::SQ)
+ {
+ return visitor(element.vr, element.as_data_set());
+ }
+ else if(is_binary(element.vr))
+ {
+ return visitor(element.vr, element.as_binary());
+ }
+ else
+ {
+ throw Exception("Unknown VR: "+as_string(element.vr));
+ }
+}
+
+}
+
+#endif // _feb2071a_de26_4adb_9305_59d0dd64c970
diff --git a/src/dcmtkpp/ElementAccessor.cpp b/src/dcmtkpp/ElementAccessor.cpp
new file mode 100644
index 0000000..fa9e2c5
--- /dev/null
+++ b/src/dcmtkpp/ElementAccessor.cpp
@@ -0,0 +1,39 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/ElementAccessor.h"
+
+#include <string>
+#include <vector>
+
+namespace dcmtkpp
+{
+
+#define DEFINE_ELEMENT_ACCESSOR(TValueType, getter, setter) \
+template<> \
+ElementAccessor<TValueType>::GetterType const \
+ElementAccessor<TValueType>\
+::element_get = getter<TValueType>; \
+\
+template<> \
+ElementAccessor<TValueType>::SetterType const \
+ElementAccessor<TValueType>\
+::element_set = setter<TValueType>;
+
+DEFINE_ELEMENT_ACCESSOR(std::string, get_string, set_string)
+DEFINE_ELEMENT_ACCESSOR(std::vector<uint8_t>, get_binary, set_binary)
+DEFINE_ELEMENT_ACCESSOR(Float32, get_default, set_default)
+DEFINE_ELEMENT_ACCESSOR(Float64, get_default, set_default)
+DEFINE_ELEMENT_ACCESSOR(Sint16, get_default, set_default)
+DEFINE_ELEMENT_ACCESSOR(Sint32, get_default, set_default)
+DEFINE_ELEMENT_ACCESSOR(Uint16, get_default, set_default)
+DEFINE_ELEMENT_ACCESSOR(Uint32, get_default, set_default)
+
+#undef DEFINE_ELEMENT_ACCESSOR
+
+}
diff --git a/src/dcmtkpp/ElementAccessor.h b/src/dcmtkpp/ElementAccessor.h
new file mode 100644
index 0000000..784614c
--- /dev/null
+++ b/src/dcmtkpp/ElementAccessor.h
@@ -0,0 +1,63 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _dfa4858b_1c9d_4ce9_b220_a1c15d873602
+#define _dfa4858b_1c9d_4ce9_b220_a1c15d873602
+
+#include <functional>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcelem.h>
+#include <dcmtk/dcmdata/dcdatset.h>
+
+#include "dcmtkpp/ElementTraits.h"
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Generic access to values in DcmElement.
+template<typename TValueType>
+struct ElementAccessor
+{
+ /// @brief C++ type of the VR.
+ typedef TValueType ValueType;
+
+ /// @brief Getter type.
+ typedef std::function<
+ ValueType(DcmElement const &, unsigned long const)> GetterType;
+
+ /// @brief Return the value in the element.
+ static GetterType const element_get;
+
+ /// @brief Setter type.
+ typedef std::function<
+ void(DcmElement &, ValueType const &, unsigned long const)> SetterType;
+
+ /// @brief Set the value in the element.
+ static SetterType const element_set;
+
+ /// @brief Test whether the data set contains a given tag.
+ static bool has(DcmDataset const & dataset, DcmTagKey const & tag);
+
+ /// @brief Return the value of an element in a dataset.
+ static ValueType get(
+ DcmDataset const & dataset,
+ DcmTagKey const tag, unsigned int const position=0);
+
+ /// @brief Set the value of an element in a dataset.
+ static void set(
+ DcmDataset & dataset,
+ DcmTagKey const tag, ValueType const & value, unsigned int const position=0);
+};
+
+}
+
+#include "ElementAccessor.txx"
+
+#endif // _dfa4858b_1c9d_4ce9_b220_a1c15d873602
diff --git a/src/dcmtkpp/ElementAccessor.txx b/src/dcmtkpp/ElementAccessor.txx
new file mode 100644
index 0000000..586280a
--- /dev/null
+++ b/src/dcmtkpp/ElementAccessor.txx
@@ -0,0 +1,207 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _f9af3e63_3597_4513_8c10_b55058f5370b
+#define _f9af3e63_3597_4513_8c10_b55058f5370b
+
+#include "ElementAccessor.h"
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcdatset.h>
+#include <dcmtk/dcmdata/dcelem.h>
+#include <dcmtk/dcmdata/dcerror.h>
+#include <dcmtk/ofstd/ofstring.h>
+
+namespace dcmtkpp
+{
+
+template<typename TValueType>
+bool
+ElementAccessor<TValueType>
+::has(DcmDataset const & dataset, DcmTagKey const & tag)
+{
+ DcmElement * dummy;
+ OFCondition const condition =
+ const_cast<DcmDataset&>(dataset).findAndGetElement(tag, dummy);
+ if(condition.good())
+ {
+ return true;
+ }
+ else if(condition == EC_TagNotFound)
+ {
+ return false;
+ }
+ else
+ {
+ throw Exception(condition);
+ }
+}
+
+template<typename TValueType>
+TValueType
+ElementAccessor<TValueType>
+::get(
+ DcmDataset const & dataset,
+ DcmTagKey const tag, unsigned int const position)
+{
+ DcmElement * element;
+ OFCondition const condition =
+ const_cast<DcmDataset &>(dataset).findAndGetElement(tag, element);
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+
+ return element_get(*element, position);
+}
+
+template<typename TValueType>
+void
+ElementAccessor<TValueType>
+::set(
+ DcmDataset & dataset,
+ DcmTagKey const tag, ValueType const & value, unsigned int const position)
+{
+ DcmElement * element;
+ OFCondition const get_condition = dataset.findAndGetElement(tag, element);
+ if(get_condition.bad())
+ {
+ OFCondition const insert_condition = dataset.insertEmptyElement(tag);
+ if(insert_condition.bad())
+ {
+ throw Exception(insert_condition);
+ }
+
+ OFCondition const new_get_condition =
+ dataset.findAndGetElement(tag, element);
+ if(new_get_condition.bad())
+ {
+ throw Exception(insert_condition);
+ }
+ }
+
+ element_set(*element, value, position);
+}
+
+template<typename TValueType>
+TValueType
+get_default(DcmElement const & element, unsigned long const position)
+{
+ TValueType value;
+ OFCondition const & condition =
+ ElementTraits<TValueType>::getter(
+ const_cast<DcmElement&>(element), value, position);
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+
+ return value;
+}
+
+template<typename TValueType>
+void
+set_default(
+ DcmElement & element, TValueType const & value,
+ unsigned long const position)
+{
+ OFCondition const condition = ElementTraits<TValueType>::setter(element, value, position);
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+}
+
+template<typename TValueType>
+TValueType
+get_string(DcmElement const & element, unsigned long const position)
+{
+ OFString value;
+ ElementTraits<OFString>::getter(const_cast<DcmElement&>(element), value, position);
+
+ return std::string(value.c_str());
+}
+
+template<typename TValueType>
+void
+set_string(
+ DcmElement & element, TValueType const & value,
+ unsigned long const position)
+{
+ OFString const value_dcmtk(value.c_str(), value.size());
+ OFCondition const condition = ElementTraits<OFString>::setter(
+ element, value_dcmtk, position);
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+}
+
+template<typename TValueType>
+TValueType
+get_binary(DcmElement const & element, unsigned long const position)
+{
+ if(position != 0)
+ {
+ throw Exception("Position must be 0 for binary VRs");
+ }
+
+ DcmEVR const evr = element.getTag().getVR().getValidEVR();
+
+ TValueType result;
+ OFCondition condition;
+
+ typename TValueType::value_type * data=NULL;
+ if(evr == EVR_OB || evr == EVR_UN)
+ {
+ Uint8 * typed_data;
+ condition = const_cast<DcmElement&>(element).getUint8Array(typed_data);
+ data = reinterpret_cast<typename TValueType::value_type *>(typed_data);
+ }
+ else if(evr == EVR_OW)
+ {
+ Uint16 * typed_data;
+ condition = const_cast<DcmElement&>(element).getUint16Array(typed_data);
+ data = reinterpret_cast<typename TValueType::value_type *>(typed_data);
+ }
+ else if(evr == EVR_OF)
+ {
+ Float32 * typed_data;
+ condition = const_cast<DcmElement&>(element).getFloat32Array(typed_data);
+ data = reinterpret_cast<typename TValueType::value_type *>(typed_data);
+ }
+ else
+ {
+ throw Exception(
+ std::string("Unknown VR: ") +
+ element.getTag().getVR().getValidVRName());
+ }
+
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+
+ result.resize(element.getLengthField());
+ std::copy(data, data+element.getLengthField(), result.begin());
+
+ return result;
+}
+
+template<typename TValueType>
+void
+set_binary(
+ DcmElement & element, TValueType const & value,
+ unsigned long const position)
+{
+
+}
+
+}
+
+#endif // _f9af3e63_3597_4513_8c10_b55058f5370b
diff --git a/src/dcmtkpp/ElementTraits.cpp b/src/dcmtkpp/ElementTraits.cpp
new file mode 100644
index 0000000..37492fd
--- /dev/null
+++ b/src/dcmtkpp/ElementTraits.cpp
@@ -0,0 +1,77 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/ElementTraits.h"
+
+#include <functional>
+#include <string>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcelem.h>
+#include <dcmtk/dcmdata/dcvr.h>
+
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+OFCondition
+getString(DcmElement & element, OFString & value, unsigned long const position)
+{
+ OFCondition condition;
+
+ DcmEVR const evr = element.getTag().getVR().getValidEVR();
+ if(evr == EVR_OB || evr == EVR_OF || evr == EVR_OW || evr == EVR_UN)
+ {
+ if(position != 0)
+ {
+ throw Exception("Position must be 0 for binary VRs");
+ }
+ condition = element.getOFStringArray(value);
+ }
+ else
+ {
+ condition = element.getOFString(value, position);
+ }
+
+ return condition;
+}
+
+OFCondition
+putString(DcmElement & element, OFString const value, unsigned long const position)
+{
+ if(position != 0)
+ {
+ throw Exception("Position must be 0");
+ }
+
+ return element.putOFStringArray(value);
+}
+
+#define DEFINE_ELEMENT_TRAITS(TValueType, getter_, setter_) \
+template<> \
+ElementTraits<TValueType>::GetterType const \
+ElementTraits<TValueType>\
+::getter = getter_; \
+\
+template<> \
+ElementTraits<TValueType>::SetterType const \
+ElementTraits<TValueType>\
+::setter = setter_;
+
+DEFINE_ELEMENT_TRAITS(OFString, getString, putString)
+DEFINE_ELEMENT_TRAITS(Float32, &DcmElement::getFloat32, &DcmElement::putFloat32)
+DEFINE_ELEMENT_TRAITS(Float64, &DcmElement::getFloat64, &DcmElement::putFloat64)
+DEFINE_ELEMENT_TRAITS(Sint16, &DcmElement::getSint16, &DcmElement::putSint16)
+DEFINE_ELEMENT_TRAITS(Sint32, &DcmElement::getSint32, &DcmElement::putSint32)
+DEFINE_ELEMENT_TRAITS(Uint16, &DcmElement::getUint16, &DcmElement::putUint16)
+DEFINE_ELEMENT_TRAITS(Uint32, &DcmElement::getUint32, &DcmElement::putUint32)
+
+#undef DEFINE_ELEMENT_TRAITS
+
+}
diff --git a/src/dcmtkpp/ElementTraits.h b/src/dcmtkpp/ElementTraits.h
new file mode 100644
index 0000000..60c4904
--- /dev/null
+++ b/src/dcmtkpp/ElementTraits.h
@@ -0,0 +1,47 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _3ae28d18_6f01_4e10_98e2_1c0d21fdcab7
+#define _3ae28d18_6f01_4e10_98e2_1c0d21fdcab7
+
+#include <functional>
+#include <string>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcelem.h>
+#include <dcmtk/dcmdata/dcvr.h>
+
+namespace dcmtkpp
+{
+
+/**
+ * @class dcmtkpp::ElementTraits
+ * @brief Traits for generic data access to values of DcmElement.
+ *
+ * The members are:
+ * - GetterType: the type of the getter function
+ * - SetterType: the type of the setter function
+ * - getter: the getter function (one of the get??? functions of DcmElement)
+ * - setter: the setter function (one of the put??? functions of DcmElement)
+ */
+template<typename TValueType>
+struct ElementTraits
+{
+ /** @brief Type of the getter function. */
+ typedef std::function<OFCondition(DcmElement &, TValueType &, unsigned long const)> GetterType;
+ /** @brief Getter function (one of the get??? functions of DcmElement). */
+ static GetterType const getter;
+ /** @brief Type of the setter function. */
+ typedef std::function<OFCondition(DcmElement &, TValueType const, unsigned long const)> SetterType;
+ /** @brief Setter function (one of the put??? functions of DcmElement). */
+ static SetterType const setter;
+};
+
+}
+
+#endif // _3ae28d18_6f01_4e10_98e2_1c0d21fdcab7
diff --git a/src/dcmtkpp/Exception.cpp b/src/dcmtkpp/Exception.cpp
new file mode 100644
index 0000000..cfe9123
--- /dev/null
+++ b/src/dcmtkpp/Exception.cpp
@@ -0,0 +1,71 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/Exception.h"
+
+#include <string>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/ofstd/ofcond.h>
+
+namespace dcmtkpp
+{
+
+Exception
+::Exception(std::string const & message)
+: _source(Source::Message), _message(message), _condition()
+{
+ // Nothing else.
+}
+
+Exception
+::Exception(OFCondition const & condition)
+: _source(Source::Condition), _message(), _condition(condition)
+{
+ // Nothing else.
+}
+
+Exception
+::~Exception() throw()
+{
+ // Nothing to do.
+}
+
+char const *
+Exception
+::what() const throw()
+{
+ if(this->_source == Source::Message)
+ {
+ return this->_message.c_str();
+ }
+ else if(this->_source == Source::Condition)
+ {
+ return this->_condition.text();
+ }
+}
+
+Exception::Source
+Exception
+::get_source() const
+{
+ return this->_source;
+}
+
+OFCondition const &
+Exception
+::get_condition() const
+{
+ if(this->_source != Source::Condition)
+ {
+ throw Exception("Wrong source");
+ }
+ return this->_condition;
+}
+
+}
diff --git a/src/dcmtkpp/Exception.h b/src/dcmtkpp/Exception.h
new file mode 100644
index 0000000..a4c9bc0
--- /dev/null
+++ b/src/dcmtkpp/Exception.h
@@ -0,0 +1,66 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _b9607695_cb3b_4188_8caa_bc8bb051ef28
+#define _b9607695_cb3b_4188_8caa_bc8bb051ef28
+
+#include <exception>
+#include <string>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/ofstd/ofcond.h>
+
+namespace dcmtkpp
+{
+
+/// @brief Base class for dcmtkpp exceptions.
+class Exception: public std::exception
+{
+public:
+ /**
+ * @brief Source of the Exception: either a message string or an
+ * OFCondition.
+ */
+ enum class Source { Message, Condition };
+
+ /// @brief Message string constructor, set the source to Source::Message.
+ Exception(std::string const & message);
+
+ /// @brief Condition constructor, set the source to Source::Condition.
+ Exception(OFCondition const & condition);
+
+ /// @brief Destructor.
+ virtual ~Exception() throw();
+
+ /**
+ * @brief Return the reason for the exception.
+ *
+ * The reason for the exception is set to the message (for Source::Message) or
+ * to the text of the condition (for Source::Condition).
+ */
+ virtual const char* what() const throw();
+
+ /// @brief Return the exception source.
+ Source get_source() const;
+
+ /**
+ * @brief Return the condition that was used to create this exception.
+ *
+ * If the source is not Source::Condition, throw an exception.
+ */
+ OFCondition const & get_condition() const;
+
+private:
+ Source _source;
+ std::string _message;
+ OFCondition _condition;
+};
+
+}
+
+#endif // _b9607695_cb3b_4188_8caa_bc8bb051ef28
diff --git a/src/dcmtkpp/FindSCU.cpp b/src/dcmtkpp/FindSCU.cpp
new file mode 100644
index 0000000..e5650f0
--- /dev/null
+++ b/src/dcmtkpp/FindSCU.cpp
@@ -0,0 +1,87 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/FindSCU.h"
+
+#include <functional>
+#include <sstream>
+#include <vector>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/CFindRequest.h"
+#include "dcmtkpp/CFindResponse.h"
+
+namespace dcmtkpp
+{
+
+FindSCU
+::~FindSCU()
+{
+ // Nothing to do
+}
+
+void
+FindSCU
+::find(DataSet const & query, Callback callback) const
+{
+ CFindRequest request(
+ this->_association->get_association()->nextMsgID++,
+ this->_affected_sop_class, Message::Priority::MEDIUM, query);
+ this->_send(request, this->_affected_sop_class);
+
+ // Receive the responses
+ bool done = false;
+ while(!done)
+ {
+ // FIXME: include progress callback
+ auto response = this->_receive<CFindResponse>();
+
+ if(response.get_message_id_being_responded_to() != request.get_message_id())
+ {
+ std::ostringstream message;
+ message << "DIMSE: Unexpected Response MsgId: "
+ << response.get_message_id_being_responded_to()
+ << "(expected: " << request.get_message_id() << ")";
+ throw Exception(message.str());
+ }
+ if(response.has_affected_sop_class_uid() &&
+ response.get_affected_sop_class_uid() != request.get_affected_sop_class_uid())
+ {
+ std::ostringstream message;
+ message << "DIMSE: Unexpected Response Affected SOP Class UID: "
+ << response.get_affected_sop_class_uid()
+ << " (expected: " << request.get_affected_sop_class_uid() << ")";
+ throw Exception(message.str());
+ }
+
+ done = !DICOM_PENDING_STATUS(response.get_status());
+ if(!done)
+ {
+ callback(response.get_data_set());
+ }
+ }
+}
+
+std::vector<DataSet>
+FindSCU
+::find(DataSet const & query) const
+{
+ std::vector<DataSet> result;
+ auto callback = [&result](DataSet const & dataset) {
+ result.push_back(dataset);
+ };
+ this->find(query, callback);
+
+ return result;
+}
+
+}
diff --git a/src/dcmtkpp/FindSCU.h b/src/dcmtkpp/FindSCU.h
new file mode 100644
index 0000000..f1fa84e
--- /dev/null
+++ b/src/dcmtkpp/FindSCU.h
@@ -0,0 +1,42 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _0106eb3a_4e02_4d7c_93bf_4d53dcafbb05
+#define _0106eb3a_4e02_4d7c_93bf_4d53dcafbb05
+
+#include <vector>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/SCU.h"
+
+namespace dcmtkpp
+{
+
+/// @brief SCU for C-FIND services.
+class FindSCU: public SCU
+{
+public:
+ /// @brief Callback called when a response is received.
+ typedef std::function<void(DataSet const &)> Callback;
+
+ /// @brief Destructor.
+ virtual ~FindSCU();
+
+ /// @brief Perform the C-FIND using an optional callback.
+ void find(DataSet const & query, Callback callback) const;
+
+ /**
+ * @brief Return a list of datasets matching the query. The user is
+ * responsible for the de-allocation of the matches.
+ */
+ std::vector<DataSet> find(DataSet const & query) const;
+};
+
+}
+
+#endif // _0106eb3a_4e02_4d7c_93bf_4d53dcafbb05
diff --git a/src/dcmtkpp/GetSCU.cpp b/src/dcmtkpp/GetSCU.cpp
new file mode 100644
index 0000000..52fa1fb
--- /dev/null
+++ b/src/dcmtkpp/GetSCU.cpp
@@ -0,0 +1,105 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/GetSCU.h"
+
+#include <functional>
+#include <sstream>
+#include <vector>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CGetRequest.h"
+#include "dcmtkpp/CGetResponse.h"
+#include "dcmtkpp/CStoreRequest.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+GetSCU
+::~GetSCU()
+{
+ // Nothing to do
+}
+
+void
+GetSCU
+::get(DataSet const & query, Callback callback) const
+{
+ // Send the request
+ CGetRequest request(this->_association->get_association()->nextMsgID++,
+ this->_affected_sop_class, Message::Priority::MEDIUM, query);
+ this->_send(request, this->_affected_sop_class);
+
+ // Receive the responses
+ bool done = false;
+ while(!done)
+ {
+ Message const message = this->_receive();
+
+ if(message.get_command_field() == Message::Command::C_GET_RSP)
+ {
+ done = this->_get_response(CGetResponse(message));
+ }
+ else if(message.get_command_field() == Message::Command::C_STORE_RQ)
+ {
+ try
+ {
+ this->_store_request(CStoreRequest(message), callback);
+ }
+ catch(...)
+ {
+ // FIXME: logging
+ done = true;
+ }
+ }
+ else
+ {
+ std::ostringstream exception_message;
+ exception_message << "DIMSE: Unexpected Response Command Field: 0x"
+ << std::hex << message.get_command_field();
+ throw Exception(exception_message.str());
+ }
+ }
+}
+
+std::vector<DataSet>
+GetSCU
+::get(DataSet const & query) const
+{
+ std::vector<DataSet> result;
+ auto callback = [&result](DataSet const & dataset) {
+ result.push_back(dataset);
+ };
+ this->get(query, callback);
+
+ return result;
+}
+
+bool
+GetSCU
+::_get_response(CGetResponse const & response) const
+{
+ bool const done = (response.get_status() != STATUS_Pending);
+ return done;
+}
+
+void
+GetSCU
+::_store_request(CStoreRequest const & request, Callback callback) const
+{
+ StoreSCP scp;
+ scp.set_network(this->get_network());
+ scp.set_association(this->get_association());
+ scp.store(request, callback);
+}
+
+}
diff --git a/src/dcmtkpp/GetSCU.h b/src/dcmtkpp/GetSCU.h
new file mode 100644
index 0000000..acc72bf
--- /dev/null
+++ b/src/dcmtkpp/GetSCU.h
@@ -0,0 +1,49 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _f82a15e2_fd13_44b5_af7d_c6983494c9c6
+#define _f82a15e2_fd13_44b5_af7d_c6983494c9c6
+
+#include "SCU.h"
+
+#include <vector>
+
+#include "dcmtkpp/CGetResponse.h"
+#include "dcmtkpp/CStoreRequest.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/StoreSCP.h"
+
+namespace dcmtkpp
+{
+
+/// @brief SCU for C-GET services.
+class GetSCU: public SCU
+{
+public:
+ /// @brief Callback called when a response is received.
+ typedef StoreSCP::Callback Callback;
+
+ /// @brief Destructor.
+ virtual ~GetSCU();
+
+ /// @brief Perform the C-GET using an optional callback.
+ void get(DataSet const & query, Callback callback) const;
+
+ /**
+ * @brief Return a list of datasets matching the query.
+ */
+ std::vector<DataSet> get(DataSet const & query) const;
+
+private:
+ bool _get_response(CGetResponse const & response) const;
+ void _store_request(CStoreRequest const & request, Callback callback) const;
+};
+
+}
+
+#endif // _f82a15e2_fd13_44b5_af7d_c6983494c9c6
diff --git a/src/dcmtkpp/Message.cpp b/src/dcmtkpp/Message.cpp
new file mode 100644
index 0000000..fed075c
--- /dev/null
+++ b/src/dcmtkpp/Message.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "Message.h"
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+Message
+::Message()
+{
+ this->_command_set.add(registry::CommandDataSetType, { DataSetType::ABSENT });
+}
+
+Message
+::Message(DataSet const & command_set)
+: _command_set(command_set)
+{
+ if(!this->_command_set.has(registry::CommandDataSetType))
+ {
+ this->_command_set.add(registry::CommandDataSetType, VR::US);
+ }
+ this->_command_set.as_int(registry::CommandDataSetType) = { DataSetType::ABSENT };
+}
+
+Message
+::Message(DataSet const & command_set, DataSet const & data_set)
+: _command_set(command_set)
+{
+ if(!this->_command_set.has(registry::CommandDataSetType))
+ {
+ this->_command_set.add(registry::CommandDataSetType, VR::US);
+ }
+ this->set_data_set(data_set);
+}
+
+Message
+::~Message()
+{
+ // Nothing to do.
+}
+
+DataSet const &
+Message
+::get_command_set() const
+{
+ return this->_command_set;
+}
+
+bool
+Message
+::has_data_set() const
+{
+ return (this->_command_set.as_int(registry::CommandDataSetType, 0) == DataSetType::PRESENT);
+}
+
+DataSet const &
+Message
+::get_data_set() const
+{
+ if(!this->has_data_set())
+ {
+ throw Exception("No data set in message");
+ }
+ return this->_data_set;
+}
+
+void
+Message
+::set_data_set(DataSet const & data_set)
+{
+ this->_data_set = data_set;
+ this->_command_set.as_int(registry::CommandDataSetType) = { DataSetType::PRESENT };
+}
+
+void
+Message
+::delete_data_set()
+{
+ this->_command_set.as_int(registry::CommandDataSetType) = { DataSetType::ABSENT };
+ this->_data_set = DataSet();
+}
+
+}
diff --git a/src/dcmtkpp/Message.h b/src/dcmtkpp/Message.h
new file mode 100644
index 0000000..d540fd6
--- /dev/null
+++ b/src/dcmtkpp/Message.h
@@ -0,0 +1,178 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _dcfa5213_ad7e_4194_8b4b_e630aa0df2e8
+#define _dcfa5213_ad7e_4194_8b4b_e630aa0df2e8
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+#define DCMTKPP_MESSAGE_MANDATORY_FIELD_MACRO(name, tag, TValueType, function) \
+ /** @brief Return the tag element of the command set. */ \
+ TValueType const & get_##name() const \
+ { \
+ auto const & data = this->_command_set.function(tag); \
+ if(data.empty()) \
+ { \
+ throw Exception("Empty element"); \
+ } \
+ return data[0]; \
+ } \
+ /** @brief Set the tag element of the command set. */ \
+ void set_##name(TValueType const & value) \
+ { \
+ if(!this->_command_set.has(tag)) \
+ { \
+ this->_command_set.add(tag); \
+ } \
+ this->_command_set.function(tag) = { value }; \
+ }
+
+#define DCMTKPP_MESSAGE_OPTIONAL_FIELD_MACRO(name, tag, TValueType, function) \
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_MACRO(name, tag, TValueType, function) \
+ bool has_##name() const \
+ { \
+ return this->_command_set.has(tag);; \
+ } \
+ void delete_##name() \
+ { \
+ this->_command_set.remove(tag); \
+ }
+
+#define DCMTKPP_MESSAGE_SET_OPTIONAL_FIELD_MACRO(dataset, name, tag, function) \
+ if(dataset.has(tag)) \
+ { \
+ this->set_##name(dataset.function(tag, 0)); \
+ }
+
+#define DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(name, tag) \
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_MACRO(name, tag, Value::Integer, as_int)
+
+#define DCMTKPP_MESSAGE_MANDATORY_FIELD_STRING_MACRO(name, tag) \
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_MACRO(name, tag, Value::String, as_string)
+
+#define DCMTKPP_MESSAGE_OPTIONAL_FIELD_INTEGER_MACRO(name, tag) \
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_MACRO(name, tag, Value::Integer, as_int)
+
+#define DCMTKPP_MESSAGE_OPTIONAL_FIELD_STRING_MACRO(name, tag) \
+ DCMTKPP_MESSAGE_OPTIONAL_FIELD_MACRO(name, tag, Value::String, as_string)
+
+/**
+ * @brief Base class for all DIMSE messages.
+ */
+class Message
+{
+public:
+ struct Command
+ {
+ enum Type
+ {
+ C_STORE_RQ = 0x0001,
+ C_STORE_RSP = 0x8001,
+
+ C_FIND_RQ = 0x0020,
+ C_FIND_RSP = 0x8020,
+
+ C_CANCEL_RQ = 0x0FFF,
+
+ C_GET_RQ = 0x0010,
+ C_GET_RSP = 0x8010,
+
+ 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,
+ };
+ };
+
+ struct Priority
+ {
+ enum Type
+ {
+ LOW = 0x0002,
+ MEDIUM = 0x0000,
+ HIGH = 0x0001,
+ };
+ };
+
+ struct DataSetType
+ {
+ enum Type
+ {
+ PRESENT = 0x0000,
+ ABSENT = 0x0101,
+ };
+ };
+
+ /// @brief Create a message with an empty command set and an empty data set.
+ Message();
+
+ /// @brief Create a message from existing data.
+ Message(DataSet const & command_set);
+
+ /// @brief Create a message from existing data.
+ Message(DataSet const & command_set, DataSet const & data_set);
+
+ /// @brief Destructor;
+ virtual ~Message();
+
+ /// @brief Return the command set of the message.
+ DataSet const & get_command_set() const;
+
+ /// @brief Test whether as data set is present in the message.
+ bool has_data_set() const;
+
+ /**
+ * @brief Return the data set of the message, raise an exception if no
+ * data set is present.
+ */
+ DataSet const & get_data_set() const;
+
+ /// @brief Set the data set of the message.
+ void set_data_set(DataSet const & data_set);
+
+ /// @brief Delete the data set in this message.
+ void delete_data_set();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(
+ command_field, registry::CommandField)
+
+protected:
+ /// @brief Command set of the message.
+ DataSet _command_set;
+
+ /// @brief Data set of the message.
+ DataSet _data_set;
+};
+
+}
+
+#endif // _dcfa5213_ad7e_4194_8b4b_e630aa0df2e8
diff --git a/src/dcmtkpp/MoveSCU.cpp b/src/dcmtkpp/MoveSCU.cpp
new file mode 100644
index 0000000..9181523
--- /dev/null
+++ b/src/dcmtkpp/MoveSCU.cpp
@@ -0,0 +1,162 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/MoveSCU.h"
+
+#include <vector>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CMoveRequest.h"
+#include "dcmtkpp/CMoveResponse.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/StoreSCP.h"
+
+namespace dcmtkpp
+{
+
+MoveSCU
+::MoveSCU()
+: SCU(), _move_destination("")
+{
+ // Nothing else.
+}
+
+MoveSCU
+::~MoveSCU()
+{
+ // Nothing to do
+}
+
+std::string const &
+MoveSCU
+::get_move_destination() const
+{
+ return this->_move_destination;
+}
+
+void
+MoveSCU
+::set_move_destination(std::string const & move_destination)
+{
+ this->_move_destination = move_destination;
+}
+
+void
+MoveSCU
+::move(DataSet const & query, Callback callback) const
+{
+ // Send the request
+ CMoveRequest const request(this->_association->get_association()->nextMsgID++,
+ this->_affected_sop_class, Message::Priority::MEDIUM,
+ this->_move_destination, query);
+ this->_send(request, this->_affected_sop_class);
+
+ // Receive the responses
+ Association store_association;
+ bool done = false;
+ while(!done)
+ {
+ // Use a small timeout to avoid blocking for a long time.
+ if(!store_association.is_associated() &&
+ this->_network->is_association_waiting(1))
+ {
+ store_association.receive(*this->_network, true);
+ }
+
+ done = this->_dispatch(store_association, callback);
+ }
+}
+
+std::vector<DataSet>
+MoveSCU
+::move(DataSet const & query) const
+{
+ std::vector<DataSet> result;
+ auto callback = [&result](DataSet const & dataset) {
+ result.push_back(dataset);
+ };
+ this->move(query, callback);
+
+ return result;
+}
+
+bool
+MoveSCU
+::_dispatch(Association & association, Callback callback) const
+{
+ T_ASC_Association *associations[2];
+ int size = 0;
+
+ associations[0] = this->_association->get_association();
+ size = 1;
+ associations[1] = association.get_association();
+ if(association.is_associated())
+ {
+ ++size;
+ }
+
+ // At this point, we should have a readable association.
+ if(!ASC_selectReadableAssociation(associations, size, 1))
+ {
+ throw Exception("No readable association");
+ }
+
+ bool move_finished;
+
+ if(associations[0] != NULL)
+ {
+ move_finished = this->_handle_main_association();
+ }
+ else if(associations[1] != NULL)
+ {
+ bool const release =
+ this->_handle_store_association(association, callback);
+ if(release)
+ {
+ association.drop();
+ }
+ }
+
+ return move_finished;
+}
+
+bool
+MoveSCU
+::_handle_main_association() const
+{
+ Message const message = this->_receive();
+
+ if(message.get_command_field() != Message::Command::C_MOVE_RSP)
+ {
+ std::ostringstream exception_message;
+ exception_message << "DIMSE: Unexpected Response Command Field: 0x"
+ << std::hex << message.get_command_field();
+ throw Exception(exception_message.str());
+ }
+
+ CMoveResponse const response(message);
+ bool const done = (response.get_status() != STATUS_Pending);
+
+ return done;
+}
+
+bool
+MoveSCU
+::_handle_store_association(Association & association, Callback callback) const
+{
+ StoreSCP scp;
+ scp.set_network(this->_network);
+ scp.set_association(&association);
+ return scp.store(callback);
+}
+
+}
diff --git a/src/dcmtkpp/MoveSCU.h b/src/dcmtkpp/MoveSCU.h
new file mode 100644
index 0000000..9189309
--- /dev/null
+++ b/src/dcmtkpp/MoveSCU.h
@@ -0,0 +1,60 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _5ff4d940_4db7_4d85_9d3a_230b944b31fe
+#define _5ff4d940_4db7_4d85_9d3a_230b944b31fe
+
+#include <string>
+#include <vector>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/SCU.h"
+#include "dcmtkpp/StoreSCP.h"
+
+namespace dcmtkpp
+{
+
+/// @brief SCU for C-MOVE services.
+class MoveSCU: public SCU
+{
+public:
+ /// @brief Callback called when a response is received.
+ typedef StoreSCP::Callback Callback;
+
+ /// @brief Constructor.
+ MoveSCU();
+
+ /// @brief Destructor.
+ virtual ~MoveSCU();
+
+ /// @brief Return the AE title of the destination, defaults to "".
+ std::string const & get_move_destination() const;
+ /// @brief Set the AE title of the destination.
+ void set_move_destination(std::string const & move_destination);
+
+ /// @brief Perform the C-MOVE using a callback.
+ void move(DataSet const & query, Callback callback) const;
+
+ /**
+ * @brief Return a list of datasets matching the query.
+ */
+ std::vector<DataSet> move(DataSet const & query) const;
+
+private:
+ std::string _move_destination;
+
+ bool _dispatch(Association & association, Callback callback) const;
+
+ bool _handle_main_association() const;
+ bool _handle_store_association(Association & association, Callback callback) const;
+};
+
+}
+
+#endif // _5ff4d940_4db7_4d85_9d3a_230b944b31fe
+
diff --git a/src/dcmtkpp/Network.cpp b/src/dcmtkpp/Network.cpp
new file mode 100644
index 0000000..218b4c3
--- /dev/null
+++ b/src/dcmtkpp/Network.cpp
@@ -0,0 +1,201 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/Network.h"
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/assoc.h>
+#include <dcmtk/dcmnet/cond.h>
+
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+Network
+::Network()
+: _role(NET_REQUESTOR), _port(0), _timeout(30), _options(0), _network(NULL)
+{
+ // Nothing else.
+}
+
+Network
+::Network(T_ASC_NetworkRole role, int port, int timeout, unsigned long options)
+: _role(role), _port(port), _timeout(timeout), _options(options), _network(NULL)
+{
+ // Nothing else.
+}
+
+Network
+::Network(Network const & other)
+: _role(other.get_role()), _port(other.get_port()),
+ _timeout(other.get_timeout()), _options(other.get_options()), _network(NULL)
+{
+ // Nothing else
+}
+
+Network
+::~Network()
+{
+ if(this->is_initialized())
+ {
+ this->drop();
+ }
+}
+
+Network &
+Network
+::operator=(Network const & other)
+{
+ if(this != &other)
+ {
+ this->set_role(other.get_role());
+ this->set_port(other.get_port());
+ this->set_timeout(other.get_timeout());
+ this->set_options(other.get_options());
+ }
+
+ return *this;
+}
+
+T_ASC_NetworkRole
+Network
+::get_role() const
+{
+ return this->_role;
+}
+
+void
+Network
+::set_role(T_ASC_NetworkRole role)
+{
+ if(this->is_initialized())
+ {
+ throw Exception("Cannot set member while initialized");
+ }
+
+ this->_role = role;
+}
+
+int
+Network
+::get_port() const
+{
+ return this->_port;
+}
+
+void
+Network
+::set_port(int port)
+{
+ if(this->is_initialized())
+ {
+ throw Exception("Cannot set member while initialized");
+ }
+
+ this->_port = port;
+}
+
+int
+Network
+::get_timeout() const
+{
+ return this->_timeout;
+}
+
+void
+Network
+::set_timeout(int timeout)
+{
+ if(this->is_initialized())
+ {
+ throw Exception("Cannot set member while initialized");
+ }
+
+ this->_timeout = timeout;
+}
+
+unsigned long
+Network
+::get_options() const
+{
+ return this->_options;
+}
+
+void
+Network
+::set_options(unsigned long options)
+{
+ if(this->is_initialized())
+ {
+ throw Exception("Cannot set member while initialized");
+ }
+
+ this->_options = options;
+}
+
+void
+Network
+::initialize()
+{
+ if(this->is_initialized())
+ {
+ throw Exception("Already initialized");
+ }
+
+ OFCondition const condition = ASC_initializeNetwork(
+ this->_role, this->_port, this->_timeout, &this->_network,
+ this->_options);
+
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+}
+
+T_ASC_Network *
+Network
+::get_network()
+{
+ return this->_network;
+}
+
+bool
+Network
+::is_association_waiting(int const timeout)
+{
+ return ASC_associationWaiting(this->_network, timeout);
+}
+
+void
+Network
+::drop()
+{
+ if(!this->is_initialized())
+ {
+ throw Exception("Not initialized");
+ }
+
+ OFCondition const condition = ASC_dropNetwork(&this->_network);
+
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+
+ this->_network = NULL;
+}
+
+bool
+Network
+::is_initialized() const
+{
+ return (this->_network != NULL);
+}
+
+}
diff --git a/src/dcmtkpp/Network.h b/src/dcmtkpp/Network.h
new file mode 100644
index 0000000..7cf8acf
--- /dev/null
+++ b/src/dcmtkpp/Network.h
@@ -0,0 +1,91 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _fad49120_3f5c_447d_b0e9_72719087640c
+#define _fad49120_3f5c_447d_b0e9_72719087640c
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/assoc.h>
+
+namespace dcmtkpp
+{
+
+/**
+ * @brief Wrapper around the T_ASC_Network class.
+ *
+ * No member can be set while the network is initialized.
+ */
+class Network
+{
+public:
+ /// @brief Create a default, un-initialized, network.
+ Network();
+
+ /// @brief Create an un-initialized network.
+ Network(T_ASC_NetworkRole role, int port, int timeout, unsigned long options=0);
+
+ /// @brief Create an un-initialized network.
+ Network(Network const & other);
+
+ /// @brief Destroy the network, dropping it if necessary.
+ ~Network();
+
+ /// @brief Assing an un-initialized network; it remains un-initialized.
+ Network & operator=(Network const & other);
+
+ /// @brief Return the role of the network, defaults to NET_REQUESTOR.
+ T_ASC_NetworkRole get_role() const;
+
+ /// @brief Set the role of the network.
+ void set_role(T_ASC_NetworkRole role);
+
+ /// @brief Return the port for acceptor role, defaults to 0.
+ int get_port() const;
+
+ /// @brief Set the port for acceptor role.
+ void set_port(int port);
+
+ /// @brief Return the timeout in seconds, defaults to 30.
+ int get_timeout() const;
+
+ /// @brief Set the timeout in seconds.
+ void set_timeout(int timeout);
+
+ /// @brief Return the options, defaults to 0.
+ unsigned long get_options() const;
+
+ /// @brief the set options.
+ void set_options(unsigned long options);
+
+ /// @brief Initialize the network.
+ void initialize();
+
+ /// @brief Return the underlying DCMTK object.
+ T_ASC_Network * get_network();
+
+ /// @brief Test whether an association request is waiting.
+ bool is_association_waiting(int const timeout);
+
+ /// @brief Drop (i.e. un-initialize) the network.
+ void drop();
+
+ /// @brief Test whether the network is initialized.
+ bool is_initialized() const;
+
+private:
+ T_ASC_NetworkRole _role;
+ int _port;
+ int _timeout;
+ unsigned long _options;
+
+ T_ASC_Network * _network;
+};
+
+}
+
+#endif // _fad49120_3f5c_447d_b0e9_72719087640c
diff --git a/src/dcmtkpp/Request.cpp b/src/dcmtkpp/Request.cpp
new file mode 100644
index 0000000..403fbd0
--- /dev/null
+++ b/src/dcmtkpp/Request.cpp
@@ -0,0 +1,38 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "Request.h"
+
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+Request
+::Request(Value::Integer message_id)
+: Message()
+{
+ this->set_message_id(message_id);
+}
+
+Request
+::Request(Message const & message)
+: Message()
+{
+ this->set_message_id(message.get_command_set().as_int(registry::MessageID, 0));
+}
+
+Request
+::~Request()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/Request.h b/src/dcmtkpp/Request.h
new file mode 100644
index 0000000..6b74ad2
--- /dev/null
+++ b/src/dcmtkpp/Request.h
@@ -0,0 +1,43 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _8d06a300_6aee_4d1f_bf10_ecdf4916ae9f
+#define _8d06a300_6aee_4d1f_bf10_ecdf4916ae9f
+
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Base class for all DIMSE request messages.
+class Request: public Message
+{
+public:
+ /// @brief Create a request with given Message ID.
+ Request(Value::Integer message_id);
+
+ /**
+ * @brief Create a request from the Message ID stored in the message
+ * command set.
+ *
+ * Raise an exception is either of this element is missing.
+ */
+ Request(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~Request();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(
+ message_id, registry::MessageID)
+};
+
+}
+
+#endif // _8d06a300_6aee_4d1f_bf10_ecdf4916ae9f
diff --git a/src/dcmtkpp/Response.cpp b/src/dcmtkpp/Response.cpp
new file mode 100644
index 0000000..f3c2e20
--- /dev/null
+++ b/src/dcmtkpp/Response.cpp
@@ -0,0 +1,43 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "Response.h"
+
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+Response
+::Response(Value::Integer message_id_being_responded_to, Value::Integer status)
+: Message()
+{
+ this->set_message_id_being_responded_to(message_id_being_responded_to);
+ this->set_status(status);
+}
+
+Response
+::Response(Message const & message)
+: Message()
+{
+ this->set_message_id_being_responded_to(
+ message.get_command_set().as_int(
+ registry::MessageIDBeingRespondedTo, 0));
+
+ this->set_status(message.get_command_set().as_int(registry::Status, 0));
+}
+
+Response
+::~Response()
+{
+ // Nothing to do.
+}
+
+}
diff --git a/src/dcmtkpp/Response.h b/src/dcmtkpp/Response.h
new file mode 100644
index 0000000..a1a66c4
--- /dev/null
+++ b/src/dcmtkpp/Response.h
@@ -0,0 +1,44 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _0dd2e31e_212a_494a_a8d3_93b235336658
+#define _0dd2e31e_212a_494a_a8d3_93b235336658
+
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/registry.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Base class for all DIMSE response messages.
+class Response: public Message
+{
+public:
+ /// @brief Create a response with given message id and status;
+ Response(Value::Integer message_id_being_responded_to, Value::Integer status);
+
+ /**
+ * @brief Create a response from the Message ID Being Responded To and the
+ * Status stored in the message command set.
+ *
+ * Raise an exception is either of those elements is missing.
+ */
+ Response(Message const & message);
+
+ /// @brief Destructor.
+ virtual ~Response();
+
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(
+ message_id_being_responded_to, registry::MessageIDBeingRespondedTo)
+ DCMTKPP_MESSAGE_MANDATORY_FIELD_INTEGER_MACRO(status, registry::Status)
+};
+
+}
+
+#endif // _0dd2e31e_212a_494a_a8d3_93b235336658
diff --git a/src/dcmtkpp/SCP.cpp b/src/dcmtkpp/SCP.cpp
new file mode 100644
index 0000000..d24e861
--- /dev/null
+++ b/src/dcmtkpp/SCP.cpp
@@ -0,0 +1,44 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "SCP.h"
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CEchoRequest.h"
+#include "dcmtkpp/CEchoResponse.h"
+#include "dcmtkpp/ServiceRole.h"
+
+namespace dcmtkpp
+{
+
+SCP
+::SCP()
+: ServiceRole()
+{
+ // Nothing else.
+}
+
+SCP
+::~SCP()
+{
+ // Nothing to do.
+}
+
+void
+SCP
+::_send_echo_response(CEchoRequest const & request) const
+{
+ CEchoResponse response(
+ request.get_message_id(), STATUS_Success,
+ request.get_affected_sop_class_uid());
+ this->_send(response, request.get_affected_sop_class_uid());
+}
+
+}
diff --git a/src/dcmtkpp/SCP.h b/src/dcmtkpp/SCP.h
new file mode 100644
index 0000000..d6130a3
--- /dev/null
+++ b/src/dcmtkpp/SCP.h
@@ -0,0 +1,31 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _f4680d8c_18a8_4317_956d_3ae238cb39cc
+#define _f4680d8c_18a8_4317_956d_3ae238cb39cc
+
+#include "dcmtkpp/CEchoRequest.h"
+#include "dcmtkpp/ServiceRole.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Base class for all Service Class Providers.
+class SCP: public ServiceRole
+{
+public:
+ SCP();
+ virtual ~SCP();
+protected:
+ /// @brief Send a C-ECHO response.
+ void _send_echo_response(CEchoRequest const & request) const;
+};
+
+}
+
+#endif // _f4680d8c_18a8_4317_956d_3ae238cb39cc
diff --git a/src/dcmtkpp/SCU.cpp b/src/dcmtkpp/SCU.cpp
new file mode 100644
index 0000000..f455768
--- /dev/null
+++ b/src/dcmtkpp/SCU.cpp
@@ -0,0 +1,70 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/SCU.h"
+
+#include <string>
+
+#include <unistd.h>
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/CEchoRequest.h"
+#include "dcmtkpp/CEchoResponse.h"
+#include "dcmtkpp/Message.h"
+
+namespace dcmtkpp
+{
+
+SCU
+::SCU()
+: ServiceRole(), _affected_sop_class("")
+{
+ // Nothing else
+}
+
+SCU
+::~SCU()
+{
+ // Nothing to do.
+}
+
+std::string const &
+SCU
+::get_affected_sop_class() const
+{
+ return this->_affected_sop_class;
+}
+
+void
+SCU
+::set_affected_sop_class(std::string const & sop_class)
+{
+ this->_affected_sop_class = sop_class;
+}
+
+void
+SCU
+::echo() const
+{
+ Uint16 const message_id = this->_association->get_association()->nextMsgID++;
+
+ CEchoRequest const request(message_id, UID_VerificationSOPClass);
+ this->_send(request, request.get_affected_sop_class_uid());
+
+ CEchoResponse const response = this->_receive<CEchoResponse>();
+ if(response.get_message_id_being_responded_to() != message_id)
+ {
+ std::ostringstream message;
+ message << "DIMSE: Unexpected Response MsgId: "
+ << response.get_message_id_being_responded_to()
+ << "(expected: " << message_id << ")";
+ throw Exception(message.str());
+ }
+}
+
+}
diff --git a/src/dcmtkpp/SCU.h b/src/dcmtkpp/SCU.h
new file mode 100644
index 0000000..efdd52c
--- /dev/null
+++ b/src/dcmtkpp/SCU.h
@@ -0,0 +1,41 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _ba1518e7_8123_46c9_81c0_65439717e40e
+#define _ba1518e7_8123_46c9_81c0_65439717e40e
+
+#include <string>
+
+#include "dcmtkpp/ServiceRole.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Base class for all Service Class Users.
+class SCU: public ServiceRole
+{
+public:
+ SCU();
+ ~SCU();
+
+ /// @brief Return the affected SOP class. Defaults to "".
+ std::string const & get_affected_sop_class() const;
+ /// @brief Set the affected SOP class
+ void set_affected_sop_class(std::string const & sop_class);
+
+ /// @brief Perform DICOM ping
+ void echo() const;
+
+protected:
+ /// @brief Affected SOP class.
+ std::string _affected_sop_class;
+};
+
+}
+
+#endif // _ba1518e7_8123_46c9_81c0_65439717e40e
diff --git a/src/dcmtkpp/ServiceRole.cpp b/src/dcmtkpp/ServiceRole.cpp
new file mode 100644
index 0000000..41cc102
--- /dev/null
+++ b/src/dcmtkpp/ServiceRole.cpp
@@ -0,0 +1,632 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "ServiceRole.h"
+
+#include <unistd.h>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcdatset.h>
+#include <dcmtk/dcmdata/dcistrmb.h>
+#include <dcmtk/dcmdata/dcostrmb.h>
+#include <dcmtk/dcmdata/dctagkey.h>
+#include <dcmtk/dcmdata/dcwcache.h>
+#include <dcmtk/dcmdata/dcxfer.h>
+#include <dcmtk/dcmnet/assoc.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/conversion.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/ElementAccessor.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+
+namespace dcmtkpp
+{
+
+ServiceRole
+::ServiceRole()
+: _association(NULL), _network(NULL)
+{
+ // Nothing else
+}
+
+ServiceRole
+::ServiceRole(ServiceRole const & other)
+: _association(other._association), _network(other._network)
+{
+ // Nothing else
+}
+
+ServiceRole const &
+ServiceRole
+::operator=(ServiceRole const & other)
+{
+ if(this != &other)
+ {
+ this->set_association(other.get_association());
+ this->set_network(other.get_network());
+ }
+
+ return *this;
+}
+
+ServiceRole
+::~ServiceRole()
+{
+ // Nothing to do.
+}
+
+Network *
+ServiceRole
+::get_network() const
+{
+ return this->_network;
+}
+
+void
+ServiceRole
+::set_network(Network * network)
+{
+ this->_network = network;
+}
+
+Association *
+ServiceRole
+::get_association() const
+{
+ return this->_association;
+}
+
+void
+ServiceRole
+::set_association(Association * association)
+{
+ this->_association = association;
+}
+
+void
+ServiceRole
+::_progress_callback_wrapper(void * data, unsigned long bytes_count)
+{
+ ProgressCallbackData * encapsulated =
+ reinterpret_cast<ProgressCallbackData*>(data);
+ encapsulated->callback(encapsulated->data, bytes_count);
+}
+
+T_ASC_PresentationContextID
+ServiceRole
+::_find_presentation_context(std::string const & abstract_syntax) const
+{
+ T_ASC_PresentationContextID const presentation_id =
+ ASC_findAcceptedPresentationContextID(
+ this->_association->get_association(),
+ abstract_syntax.c_str());
+ if(presentation_id == 0)
+ {
+ throw Exception("No Presentation Context for Get Operation");
+ }
+
+ return presentation_id;
+}
+void
+ServiceRole
+::_send(
+ Message const & message, std::string const & abstract_syntax,
+ ProgressCallback callback, void* callback_data) const
+{
+ T_ASC_PresentationContextID const presentation_context =
+ this->_find_presentation_context(abstract_syntax);
+
+ DcmDataset * command_set = dynamic_cast<DcmDataset*>(
+ convert(message.get_command_set()));
+
+ this->_send(
+ command_set,
+ presentation_context, EXS_LittleEndianImplicit,
+ DUL_COMMANDPDV, NULL, NULL);
+ if(message.has_data_set() && !message.get_data_set().empty())
+ {
+ DcmDataset * data_set = dynamic_cast<DcmDataset*>(
+ convert(message.get_data_set()));
+ // FIXME: transfer syntax
+ this->_send(
+ data_set,
+ presentation_context, EXS_LittleEndianImplicit,
+ DUL_DATASETPDV, callback, callback_data);
+ delete data_set;
+ }
+
+ delete command_set;
+}
+
+Message
+ServiceRole
+::_receive(ProgressCallback callback, void* callback_data) const
+{
+ // Receive command set
+ std::pair<DcmDataset, DUL_DATAPDV> const command =
+ this->_receive_dataset(callback, callback_data);
+ if(command.second != DUL_COMMANDPDV)
+ {
+ throw Exception("Did not receive command set");
+ }
+ DataSet const command_set = convert(const_cast<DcmDataset*>(&command.first));
+
+ // Receive potential data set
+ DataSet data_set;
+ bool has_data_set;
+ if(command_set.as_int(registry::CommandDataSetType, 0) != DIMSE_DATASET_NULL)
+ {
+ std::pair<DcmDataset, DUL_DATAPDV> const data =
+ this->_receive_dataset(callback, callback_data);
+ if(data.second != DUL_DATASETPDV)
+ {
+ throw Exception("Did not receive data set");
+ }
+ data_set = convert(const_cast<DcmDataset*>(&data.first));
+ has_data_set = true;
+ }
+ else
+ {
+ has_data_set = false;
+ }
+
+ return has_data_set?Message(command_set, data_set):Message(command_set);
+}
+
+OFCondition
+ServiceRole
+::_send(
+ DcmDataset *obj, T_ASC_PresentationContextID presID,
+ E_TransferSyntax xferSyntax, DUL_DATAPDV pdvType,
+ ProgressCallback callback, void *callbackContext) const
+ /*
+ * This function sends all information which is included in a DcmDataset object over
+ * the network which is provided in assoc.
+ *
+ * Parameters:
+ * obj - [in] Contains the information which shall be sent over the network.
+ * presId - [in] The ID of the presentation context which shall be used
+ * xferSyntax - [in] The transfer syntax which shall be used.
+ * pdvType - [in] Specifies if the information in this DcmDataset object belongs to
+ * a DIMSE command (as for example C-STORE) (DUL_COMMANDPDV) or if
+ * the information is actual instance information (DUL_DATASETPDV).
+ * callback - [in] Pointer to a function which shall be called to indicate progress.
+ * callbackContext - []
+ */
+{
+ OFBool written = OFFalse;
+ DcmWriteCache wcache;
+
+ /* we may wish to restrict output PDU size */
+ /* max PDV size is max PDU size minus 12 bytes PDU/PDV header */
+ unsigned long bufLen = this->_association->get_association()->sendPDVLength;
+ if (bufLen + 12 > dcmMaxOutgoingPDUSize.get())
+ {
+ bufLen = dcmMaxOutgoingPDUSize.get() - 12;
+ }
+
+ /* on the basis of the association's buffer, create a buffer variable that we can write to */
+ DcmOutputBufferStream outBuf(
+ this->_association->get_association()->sendPDVBuffer, bufLen);
+
+ /* prepare all elements in the DcmDataset variable for transfer */
+ obj->transferInit();
+
+ /* groupLength_encoding specifies what will be done concerning
+ * group length tags
+ */
+ E_GrpLenEncoding groupLength_encoding = g_dimse_send_groupLength_encoding;
+ /* Mind that commands must always include group length (0000,0000) and */
+ /* that commands do not contain sequences, yet */
+ if (pdvType == DUL_COMMANDPDV)
+ {
+ groupLength_encoding = EGL_withGL;
+ }
+
+ /* sequenceType_encoding specifies how sequences will be handled */
+ E_EncodingType const sequenceType_encoding = g_dimse_send_sequenceType_encoding;
+
+ /* start a loop: in each iteration information from the DcmDataset object (i.e. infor- */
+ /* mation which shall be sent) will be set in the buffer (we need more than one itera- */
+ /* tion if there is more information than the buffer can take at a time), a PDV object */
+ /* with the buffer's data will be created and assigned to a list, and finally the */
+ /* list's information will be sent over the network to the other DICOM application. */
+ OFBool last = OFFalse;
+ Uint32 bytesTransmitted = 0;
+ while (!last)
+ {
+ /* write data values which are contained in the DcmDataSet variable to the above created */
+ /* buffer. Mind the transfer syntax, the sequence type encoding, the group length encoding */
+ /* and remove all padding data elements. Depending on whether all information has been written */
+ /* to the buffer, update the variable that determines the end of the while loop. (Note that */
+ /* DcmDataset stores information about what of its content has already been sent to the buffer.) */
+ if (! written)
+ {
+ OFCondition const econd =
+ obj->write(outBuf, xferSyntax, sequenceType_encoding, &wcache,
+ groupLength_encoding, EPD_withoutPadding);
+ if (econd == EC_Normal) /* all contents have been written to the buffer */
+ {
+ written = OFTrue;
+ }
+ else if (econd == EC_StreamNotifyClient) /* no more space in buffer, _not_ all elements have been written to it */
+ {
+ // nothing to do
+ }
+ else /* some error has occurred */
+ {
+ //DCMNET_WARN(DIMSE_warn_str(assoc) << "writeBlock Failed (" << econd.text() << ")");
+ return DIMSE_SENDFAILED;
+ }
+ }
+
+ if (written)
+ {
+ outBuf.flush(); // flush stream including embedded compression codec.
+ }
+
+ /* get buffer and its length, assign to local variable */
+ void *fullBuf = NULL;
+ offile_off_t rtnLength;
+ outBuf.flushBuffer(fullBuf, rtnLength);
+
+ last = written && outBuf.isFlushed();
+
+ /* if the buffer is not empty, do something with its contents */
+ if (rtnLength > 0)
+ {
+ /* rtnLength could be odd */
+ if (rtnLength & 1)
+ {
+ /* this should only happen if we use a stream compressed transfer
+ * syntax and then only at the very end of the stream. Everything
+ * else is a failure.
+ */
+ if (!last)
+ {
+ return makeDcmnetCondition(
+ DIMSEC_SENDFAILED, OF_error,
+ "DIMSE Failed to send message: odd block length encountered");
+ }
+
+ /* since the block size is always even, block size must be larger
+ * than rtnLength, so we can safely add a pad byte (and hope that
+ * the pad byte will not confuse the receiver's decompressor).
+ */
+ unsigned char *cbuf = (unsigned char *)fullBuf;
+ cbuf[rtnLength++] = 0; // add zero pad byte
+ }
+
+ /* initialize a DUL_PDV variable with the buffer's data */
+ DUL_PDV pdv;
+ pdv.fragmentLength = OFstatic_cast(unsigned long, rtnLength);
+ pdv.presentationContextID = presID;
+ pdv.pdvType = pdvType;
+ pdv.lastPDV = last;
+ pdv.data = fullBuf;
+
+ /* append this PDV to a PDV list structure, set the counter variable */
+ /* to 1 since this structure contains only 1 element */
+ DUL_PDVLIST pdvList;
+ pdvList.count = 1;
+ pdvList.pdv = &pdv;
+
+ /* send information over the network to the other DICOM application */
+ OFCondition const dulCond = DUL_WritePDVs(
+ &this->_association->get_association()->DULassociation,
+ &pdvList);
+ if (dulCond.bad())
+ {
+ return makeDcmnetSubCondition(DIMSEC_SENDFAILED, OF_error, "DIMSE Failed to send message", dulCond);
+ }
+
+ /* count the bytes and the amount of PDVs which were transmitted */
+ bytesTransmitted += OFstatic_cast(Uint32, rtnLength);
+
+ /* execute callback function to indicate progress */
+ if(callback)
+ {
+ callback(callbackContext, bytesTransmitted);
+ }
+ }
+ }
+
+ /* indicate the end of the transfer */
+ obj->transferEnd();
+
+ return EC_Normal;
+}
+
+
+std::pair<DcmDataset, DUL_DATAPDV>
+ServiceRole::_receive_dataset(
+ ProgressCallback callback, void *callbackContext) const
+{
+ DcmDataset dataset;
+ dataset.transferInit();
+ DcmInputBufferStream buffer;
+ if(!buffer.good())
+ {
+ throw Exception(
+ makeDcmnetCondition(
+ DIMSEC_PARSEFAILED, OF_error,
+ "DIMSE: receiveCommand: Failed to initialize cmdBuf"));
+ }
+
+ /* start a loop in which we want to read a DIMSE command from the incoming socket stream. */
+ /* Since the command could stretch over more than one PDU, the use of a loop is mandatory. */
+ DUL_DATAPDV type;
+ bool last = false;
+ DIC_UL pdvCount = 0;
+ T_ASC_PresentationContextID pid = 0;
+ while(!last)
+ {
+ /* make the stream remember any unread bytes */
+ buffer.releaseBuffer();
+
+ DUL_PDV const pdv = this->_read_next_pdv();
+
+ /* if this is the first loop iteration, get the presentation context ID
+ * which is captured in the current PDV. If this is not the first loop
+ * iteration, check if the presentation context IDs in the current PDV
+ * and in the last PDV are identical. If they are not, return an error.
+ */
+ if (pdvCount == 0)
+ {
+ pid = pdv.presentationContextID;
+ }
+ else if (pdv.presentationContextID != pid)
+ {
+ char buf1[256];
+ sprintf(buf1, "DIMSE: Different PresIDs inside Command Set: %d != %d", pid, pdv.presentationContextID);
+ OFCondition subCond = makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, buf1);
+ throw Exception(
+ makeDcmnetSubCondition(
+ DIMSEC_RECEIVEFAILED, OF_error,
+ "DIMSE Failed to receive message", subCond));
+ }
+
+ /* check if the fragment length of the current PDV is odd. This should */
+ /* never happen (see DICOM standard (year 2000) part 7, annex F) (or */
+ /* the corresponding section in a later version of the standard.) */
+ if ((pdv.fragmentLength % 2) != 0)
+ {
+ /* This should NEVER happen. See Part 7, Annex F. */
+ char buf2[256];
+ sprintf(buf2, "DIMSE: Odd Fragment Length: %lu", pdv.fragmentLength);
+ throw Exception(
+ makeDcmnetCondition(DIMSEC_RECEIVEFAILED, OF_error, buf2));
+ }
+
+ /* if information is contained the PDVs fragment, we want to insert
+ * this information into the buffer
+ */
+ if (pdv.fragmentLength > 0)
+ {
+ buffer.setBuffer(pdv.data, pdv.fragmentLength);
+ }
+
+ /* if this fragment contains the last fragment of the DIMSE command,
+ * set the end of the stream
+ */
+ if (pdv.lastPDV)
+ {
+ buffer.setEos();
+ }
+
+ E_TransferSyntax transfer_syntax;
+ E_GrpLenEncoding group_length_encoding;
+ if(pdv.pdvType == DUL_COMMANDPDV)
+ {
+ /* DIMSE commands are always specified in the little endian implicit
+ * transfer syntax. Additionally, we want to remove group length
+ * tags.
+ */
+ transfer_syntax = EXS_LittleEndianImplicit;
+ group_length_encoding = EGL_withoutGL;
+ }
+ else if(pdv.pdvType == DUL_DATASETPDV)
+ {
+ /* figure out if is this a valid presentation context */
+ T_ASC_PresentationContext pc;
+ OFCondition const cond =
+ ASC_findAcceptedPresentationContext(
+ this->_association->get_association()->params, pid, &pc);
+ if (cond.bad())
+ {
+ throw Exception(makeDcmnetSubCondition(
+ DIMSEC_RECEIVEFAILED, OF_error,
+ "DIMSE Failed to receive message", cond));
+ }
+
+ /* determine the transfer syntax which is specified in the presentation context */
+ std::string const ts = pc.acceptedTransferSyntax;
+
+ /* create a DcmXfer object on the basis of the transfer syntax which was determined above */
+ DcmXfer xfer(ts.c_str());
+
+ /* check if the transfer syntax is supported by dcmtk */
+ transfer_syntax = xfer.getXfer();
+ switch (transfer_syntax)
+ {
+ case EXS_LittleEndianImplicit:
+ case EXS_LittleEndianExplicit:
+ case EXS_BigEndianExplicit:
+ case EXS_JPEGProcess1TransferSyntax:
+ case EXS_JPEGProcess2_4TransferSyntax:
+ case EXS_JPEGProcess3_5TransferSyntax:
+ case EXS_JPEGProcess6_8TransferSyntax:
+ case EXS_JPEGProcess7_9TransferSyntax:
+ case EXS_JPEGProcess10_12TransferSyntax:
+ case EXS_JPEGProcess11_13TransferSyntax:
+ case EXS_JPEGProcess14TransferSyntax:
+ case EXS_JPEGProcess15TransferSyntax:
+ case EXS_JPEGProcess16_18TransferSyntax:
+ case EXS_JPEGProcess17_19TransferSyntax:
+ case EXS_JPEGProcess20_22TransferSyntax:
+ case EXS_JPEGProcess21_23TransferSyntax:
+ case EXS_JPEGProcess24_26TransferSyntax:
+ case EXS_JPEGProcess25_27TransferSyntax:
+ case EXS_JPEGProcess28TransferSyntax:
+ case EXS_JPEGProcess29TransferSyntax:
+ case EXS_JPEGProcess14SV1TransferSyntax:
+ case EXS_RLELossless:
+ case EXS_JPEGLSLossless:
+ case EXS_JPEGLSLossy:
+ case EXS_JPEG2000LosslessOnly:
+ case EXS_JPEG2000:
+ case EXS_MPEG2MainProfileAtMainLevel:
+ case EXS_MPEG2MainProfileAtHighLevel:
+ case EXS_JPEG2000MulticomponentLosslessOnly:
+ case EXS_JPEG2000Multicomponent:
+ #ifdef WITH_ZLIB
+ case EXS_DeflatedLittleEndianExplicit:
+ #endif
+ /* OK, these can be supported */
+ break;
+ default:
+ /* all other transfer syntaxes are not supported; hence, set the error indicator variable */
+ {
+ char buf[256];
+ sprintf(
+ buf, "DIMSE Unsupported transfer syntax: %s",
+ ts.c_str());
+ OFCondition subCond = makeDcmnetCondition(
+ DIMSEC_UNSUPPORTEDTRANSFERSYNTAX, OF_error, buf);
+ throw Exception(makeDcmnetSubCondition(
+ DIMSEC_RECEIVEFAILED, OF_error,
+ "DIMSE Failed to receive message", subCond));
+ }
+ break;
+ }
+ group_length_encoding = EGL_noChange;
+ }
+ else
+ {
+ throw Exception("Unkown PDV type");
+ }
+
+ OFCondition const econd = dataset.read(
+ buffer, transfer_syntax, group_length_encoding);
+ if (econd != EC_Normal && econd != EC_StreamNotifyClient)
+ {
+ throw Exception(
+ makeDcmnetSubCondition(
+ DIMSEC_RECEIVEFAILED, OF_error,
+ "DIMSE: receiveCommand: cmdSet->read() Failed", econd));
+ }
+
+ /* update the following variables which will be evaluated at the beginning of each loop iteration. */
+ last = pdv.lastPDV;
+ type = pdv.pdvType;
+
+ /* update the counter that counts how many PDVs were received on the incoming */
+ /* socket stream. This variable will be used for determining the first */
+ /* loop iteration and dumping general information. */
+ pdvCount++;
+ }
+
+ dataset.transferEnd();
+
+ return std::make_pair(dataset, type);
+}
+
+DUL_PDV
+ServiceRole
+::_read_next_pdv() const
+ /*
+ * This function returns the next PDV which was (earlier or just now) received on the incoming
+ * socket stream. If there are no PDVs (which were already received earlier) waiting to be picked
+ * up, this function will go ahead and read a new PDU (containing one or more new PDVs) from the
+ * incoming socket stream.
+ */
+{
+ /* get the next PDV from the association, in case there are still some PDVs waiting to be picked up */
+ DUL_PDV pdv;
+ OFCondition cond = DUL_NextPDV(
+ &this->_association->get_association()->DULassociation, &pdv);
+
+ if (cond.bad())
+ {
+ /* in case DUL_NextPDV(...) did not return DUL_NORMAL, the association */
+ /* did not contain any more PDVs that are waiting to be picked up. Hence, */
+ /* we need to read new PDVs from the incoming socket stream. */
+
+ /* if the blocking mode is DIMSE_NONBLOCKING and there is no data waiting after timeout seconds, report an error */
+ if(!ASC_dataWaiting(
+ this->_association->get_association(), this->_network->get_timeout()))
+ {
+ throw Exception(DIMSE_NODATAAVAILABLE);
+ }
+
+ /* try to receive new PDVs on the incoming socket stream (in detail, try to receive one PDU) */
+ cond = DUL_ReadPDVs(
+ &this->_association->get_association()->DULassociation, NULL,
+ DUL_BLOCK, this->_network->get_timeout());
+
+ /* check return value, if it is different from DUL_PDATAPDUARRIVED, an error occurred */
+ if (cond != DUL_PDATAPDUARRIVED)
+ {
+ if (cond == DUL_NULLKEY || cond == DUL_ILLEGALKEY)
+ {
+ throw Exception(DIMSE_ILLEGALASSOCIATION);
+ }
+ else if (cond == DUL_PEERREQUESTEDRELEASE ||
+ cond == DUL_PEERABORTEDASSOCIATION)
+ {
+ throw Exception(cond);
+ }
+ else
+ {
+ throw Exception(
+ makeDcmnetSubCondition(
+ DIMSEC_READPDVFAILED, OF_error,
+ "DIMSE Read PDV failed", cond));
+ }
+ }
+
+ /* get the next PDV, assign it to pdv */
+ cond = DUL_NextPDV(
+ &this->_association->get_association()->DULassociation, &pdv);
+ if (cond.bad())
+ {
+ throw Exception(
+ makeDcmnetSubCondition(
+ DIMSEC_READPDVFAILED, OF_error,
+ "DIMSE Read PDV failed", cond));
+ }
+ }
+
+ return pdv;
+}
+
+void
+ServiceRole
+::_check_dimse_ready() const
+{
+ if(this->_network == NULL)
+ {
+ throw Exception("No network");
+ }
+ else if(!this->_network->is_initialized())
+ {
+ throw Exception("Network is not initialized");
+ }
+ else if(this->_association == NULL)
+ {
+ throw Exception("No association");
+ }
+ else if(!this->_association->is_associated())
+ {
+ throw Exception("Not associated");
+ }
+}
+
+}
diff --git a/src/dcmtkpp/ServiceRole.h b/src/dcmtkpp/ServiceRole.h
new file mode 100644
index 0000000..ec4fc93
--- /dev/null
+++ b/src/dcmtkpp/ServiceRole.h
@@ -0,0 +1,114 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _fa7d372a_dd27_4a1e_9b29_be9d5fbe602a
+#define _fa7d372a_dd27_4a1e_9b29_be9d5fbe602a
+
+#include <functional>
+#include <utility>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcdatset.h>
+#include <dcmtk/dcmnet/assoc.h>
+
+#include "dcmtkpp/Association.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/Network.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Base class for all Service Class Users and Providers.
+class ServiceRole
+{
+public:
+ /// @brief Progress callback, following the semantics of DCMTK.
+ typedef std::function<void(void *, unsigned long)> ProgressCallback;
+
+ /// @brief Create a default Service Role with no network and no association.
+ ServiceRole();
+
+ /// @brief Copy the other service role.
+ ServiceRole(ServiceRole const & other);
+
+ /// @brief Copy the other service role.
+ ServiceRole const & operator=(ServiceRole const & other);
+
+ /// @brief Destructor, network and association are not modified.
+ virtual ~ServiceRole();
+
+ /// @brief Return the network used by the ServiceRole.
+ Network * get_network() const;
+ /// @brief Set the network used by the ServiceRole.
+ void set_network(Network * network);
+
+ /// @brief Return the association used by the ServiceRole.
+ Association * get_association() const;
+ /// @brief Set the association used by the ServiceRole.
+ void set_association(Association * association);
+
+protected:
+ /// @brief Wrapper class for DMCTK progress callbacks.
+ struct ProgressCallbackData
+ {
+ /// @brief Callback function.
+ ProgressCallback callback;
+
+ /// @brief Callback data.
+ void * data;
+ };
+
+ /// @brief Network used by the ServiceRole.
+ Network * _network;
+
+ /// @brief Association used by the ServiceRole.
+ Association * _association;
+
+ /// @brief Wrapper from ProgressCallback to DIMSE_ProgressCallback.
+ static void _progress_callback_wrapper(void * data, unsigned long bytes_count);
+
+ /// @brief Find an accepted presentation context.
+ T_ASC_PresentationContextID _find_presentation_context(
+ std::string const & abstract_syntax) const;
+
+ /// @brief Send a DIMSE message.
+ void _send(
+ Message const & message, std::string const & abstract_syntax,
+ ProgressCallback callback=NULL, void* callback_data=NULL) const;
+
+ /// @brief Receive a generic DIMSE message.
+ Message _receive(ProgressCallback callback=NULL, void* callback_data=NULL) const;
+
+ /**
+ * @brief Receive a DIMSE message of specific type.
+ *
+ * Throw an exception if the received message is not of the requested type.
+ */
+ template<typename TMessage>
+ TMessage _receive(ProgressCallback callback=NULL, void* callback_data=NULL) const;
+
+private:
+ OFCondition _send(
+ DcmDataset *obj, T_ASC_PresentationContextID presID,
+ E_TransferSyntax xferSyntax, DUL_DATAPDV pdvType,
+ ProgressCallback callback, void *callbackContext) const;
+
+ std::pair<DcmDataset, DUL_DATAPDV> _receive_dataset(
+ ProgressCallback callback, void *callbackContext) const;
+
+ DUL_PDV _read_next_pdv() const;
+
+ void _check_dimse_ready() const;
+};
+
+}
+
+#include "ServiceRole.txx"
+
+#endif // _fa7d372a_dd27_4a1e_9b29_be9d5fbe602a
diff --git a/src/dcmtkpp/ServiceRole.txx b/src/dcmtkpp/ServiceRole.txx
new file mode 100644
index 0000000..8e8ccca
--- /dev/null
+++ b/src/dcmtkpp/ServiceRole.txx
@@ -0,0 +1,39 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _8ac39caa_b7b1_44a8_82fc_e8e3de18b2f8
+#define _8ac39caa_b7b1_44a8_82fc_e8e3de18b2f8
+
+#include "ServiceRole.h"
+
+#include <functional>
+#include <utility>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcdatset.h>
+#include <dcmtk/dcmnet/assoc.h>
+
+#include "dcmtkpp/Association.h"
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/Network.h"
+
+namespace dcmtkpp
+{
+
+template<typename TMessage>
+TMessage
+ServiceRole
+::_receive(ProgressCallback callback, void* callback_data) const
+{
+ Message const message = this->_receive(callback, callback_data);
+ return TMessage(message);
+}
+
+}
+
+#endif // _8ac39caa_b7b1_44a8_82fc_e8e3de18b2f8
diff --git a/src/dcmtkpp/StoreSCP.cpp b/src/dcmtkpp/StoreSCP.cpp
new file mode 100644
index 0000000..c6d152b
--- /dev/null
+++ b/src/dcmtkpp/StoreSCP.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/StoreSCP.h"
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CStoreRequest.h"
+#include "dcmtkpp/CStoreResponse.h"
+#include "dcmtkpp/DataSet.h"
+
+namespace dcmtkpp
+{
+
+bool
+StoreSCP
+::store(Callback callback) const
+{
+ Message request;
+ try
+ {
+ request = this->_receive();
+ }
+ catch(Exception const & e)
+ {
+ if(e.get_source() != Exception::Source::Condition ||
+ e.get_condition() != DUL_PEERREQUESTEDRELEASE)
+ {
+ throw;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ if(request.get_command_field() == Message::Command::C_ECHO_RQ)
+ {
+ this->_send_echo_response(CEchoRequest(request));
+ }
+ else if(request.get_command_field() == Message::Command::C_STORE_RQ)
+ {
+ this->store(CStoreRequest(request), callback);
+ request.delete_data_set();
+ }
+ else
+ {
+ std::ostringstream message;
+ message << "DIMSE: Unexpected Response Command Field: 0x"
+ << std::hex << request.get_command_field();
+ throw Exception(message.str());
+ }
+
+ return false;
+}
+
+void
+StoreSCP
+::store(CStoreRequest const & request, Callback callback) const
+{
+ // Execute user callback
+ Uint16 status = STATUS_Success;
+ if(!request.has_data_set() || request.get_data_set().empty())
+ {
+ status = STATUS_STORE_Error_CannotUnderstand;
+ }
+ else
+ {
+ try
+ {
+ callback(request.get_data_set());
+ }
+ catch(...)
+ {
+ // FIXME: logging
+ status = STATUS_STORE_Error_CannotUnderstand;
+ }
+ }
+
+ // Send store response
+ CStoreResponse response(request.get_message_id(), status);
+ response.set_affected_sop_class_uid(request.get_affected_sop_class_uid());
+ response.set_affected_sop_instance_uid(
+ request.get_affected_sop_instance_uid());
+ this->_send(response, request.get_affected_sop_class_uid());
+}
+
+}
diff --git a/src/dcmtkpp/StoreSCP.h b/src/dcmtkpp/StoreSCP.h
new file mode 100644
index 0000000..9d6c8ed
--- /dev/null
+++ b/src/dcmtkpp/StoreSCP.h
@@ -0,0 +1,43 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _fdbf3f51_91f5_464a_b449_c3f994297210
+#define _fdbf3f51_91f5_464a_b449_c3f994297210
+
+#include <functional>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/CStoreRequest.h"
+#include "dcmtkpp/SCP.h"
+
+namespace dcmtkpp
+{
+
+class StoreSCP: public SCP
+{
+public:
+ /// @brief Callback called when a response is received.
+ typedef std::function<void(DataSet const &)> Callback;
+
+ /**
+ * @brief Receive a store request and respond to it.
+ * @param callback function called with the dataset to be stored.
+ */
+ bool store(Callback callback) const;
+
+ /**
+ * @brief Respond to a store request.
+ * @param request
+ * @param callback function called with the dataset to be stored.
+ */
+ void store(CStoreRequest const & request, Callback callback) const;
+};
+
+}
+
+#endif // _fdbf3f51_91f5_464a_b449_c3f994297210
diff --git a/src/dcmtkpp/StoreSCU.cpp b/src/dcmtkpp/StoreSCU.cpp
new file mode 100644
index 0000000..3df3abe
--- /dev/null
+++ b/src/dcmtkpp/StoreSCU.cpp
@@ -0,0 +1,209 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "StoreSCU.h"
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+
+#include "dcmtkpp/CStoreRequest.h"
+#include "dcmtkpp/CStoreResponse.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/registry.h"
+
+namespace dcmtkpp
+{
+
+StoreSCU
+::~StoreSCU()
+{
+ // Nothing to do.
+}
+
+void
+StoreSCU
+::set_affected_sop_class(DataSet const & dataset)
+{
+ auto const & sop_class_uid = dataset.as_string(registry::SOPClassUID, 0);
+
+ // From dcuid.h
+ std::vector<std::string> const storage = {
+ UID_RETIRED_StoredPrintStorage,
+ UID_RETIRED_HardcopyGrayscaleImageStorage,
+ UID_RETIRED_HardcopyColorImageStorage,
+ UID_ComputedRadiographyImageStorage,
+ UID_DigitalXRayImageStorageForPresentation,
+ UID_DigitalXRayImageStorageForProcessing,
+ UID_DigitalMammographyXRayImageStorageForPresentation,
+ UID_DigitalMammographyXRayImageStorageForProcessing,
+ UID_DigitalIntraOralXRayImageStorageForPresentation,
+ UID_DigitalIntraOralXRayImageStorageForProcessing,
+ UID_CTImageStorage,
+ UID_EnhancedCTImageStorage,
+ UID_RETIRED_UltrasoundMultiframeImageStorage,
+ UID_UltrasoundMultiframeImageStorage,
+ UID_MRImageStorage,
+ UID_EnhancedMRImageStorage,
+ UID_MRSpectroscopyStorage,
+ UID_EnhancedMRColorImageStorage,
+ UID_RETIRED_NuclearMedicineImageStorage,
+ UID_RETIRED_UltrasoundImageStorage,
+ UID_UltrasoundImageStorage,
+ UID_EnhancedUSVolumeStorage,
+ UID_SecondaryCaptureImageStorage,
+ UID_MultiframeSingleBitSecondaryCaptureImageStorage,
+ UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage,
+ UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage,
+ UID_MultiframeTrueColorSecondaryCaptureImageStorage,
+ UID_RETIRED_StandaloneOverlayStorage,
+ UID_RETIRED_StandaloneCurveStorage,
+ UID_TwelveLeadECGWaveformStorage,
+ UID_GeneralECGWaveformStorage,
+ UID_AmbulatoryECGWaveformStorage,
+ UID_HemodynamicWaveformStorage,
+ UID_CardiacElectrophysiologyWaveformStorage,
+ UID_BasicVoiceAudioWaveformStorage,
+ UID_GeneralAudioWaveformStorage,
+ UID_ArterialPulseWaveformStorage,
+ UID_RespiratoryWaveformStorage,
+ UID_RETIRED_StandaloneModalityLUTStorage,
+ UID_RETIRED_StandaloneVOILUTStorage,
+ UID_GrayscaleSoftcopyPresentationStateStorage,
+ UID_ColorSoftcopyPresentationStateStorage,
+ UID_PseudoColorSoftcopyPresentationStateStorage,
+ UID_BlendingSoftcopyPresentationStateStorage,
+ UID_XAXRFGrayscaleSoftcopyPresentationStateStorage,
+ UID_XRayAngiographicImageStorage,
+ UID_EnhancedXAImageStorage,
+ UID_XRayRadiofluoroscopicImageStorage,
+ UID_EnhancedXRFImageStorage,
+ UID_XRay3DAngiographicImageStorage,
+ UID_XRay3DCraniofacialImageStorage,
+ UID_BreastTomosynthesisImageStorage,
+ UID_RETIRED_XRayAngiographicBiPlaneImageStorage,
+ UID_NuclearMedicineImageStorage,
+ UID_RawDataStorage,
+ UID_SpatialRegistrationStorage,
+ UID_SpatialFiducialsStorage,
+ UID_DeformableSpatialRegistrationStorage,
+ UID_SegmentationStorage,
+ UID_SurfaceSegmentationStorage,
+ UID_RealWorldValueMappingStorage,
+ UID_RETIRED_VLImageStorage,
+ UID_VLEndoscopicImageStorage,
+ UID_VideoEndoscopicImageStorage,
+ UID_VLMicroscopicImageStorage,
+ UID_VideoMicroscopicImageStorage,
+ UID_VLSlideCoordinatesMicroscopicImageStorage,
+ UID_VLPhotographicImageStorage,
+ UID_VideoPhotographicImageStorage,
+ UID_OphthalmicPhotography8BitImageStorage,
+ UID_OphthalmicPhotography16BitImageStorage,
+ UID_StereometricRelationshipStorage,
+ UID_OphthalmicTomographyImageStorage,
+ UID_VLWholeSlideMicroscopyImageStorage,
+ UID_RETIRED_VLMultiFrameImageStorage,
+ UID_LensometryMeasurementsStorage,
+ UID_AutorefractionMeasurementsStorage,
+ UID_KeratometryMeasurementsStorage,
+ UID_SubjectiveRefractionMeasurementsStorage,
+ UID_VisualAcuityMeasurementsStorage,
+ UID_SpectaclePrescriptionReportStorage,
+ UID_OphthalmicAxialMeasurementsStorage,
+ UID_IntraocularLensCalculationsStorage,
+ UID_MacularGridThicknessAndVolumeReportStorage,
+ UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage,
+ UID_BasicTextSRStorage,
+ UID_EnhancedSRStorage,
+ UID_ComprehensiveSRStorage,
+ UID_ProcedureLogStorage,
+ UID_MammographyCADSRStorage,
+ UID_KeyObjectSelectionDocumentStorage,
+ UID_ChestCADSRStorage,
+ UID_XRayRadiationDoseSRStorage,
+ UID_ColonCADSRStorage,
+ UID_ImplantationPlanSRDocumentStorage,
+ UID_EncapsulatedPDFStorage,
+ UID_EncapsulatedCDAStorage,
+ UID_PositronEmissionTomographyImageStorage,
+ UID_RETIRED_StandalonePETCurveStorage,
+ UID_EnhancedPETImageStorage,
+ UID_BasicStructuredDisplayStorage,
+ UID_RTImageStorage,
+ UID_RTDoseStorage,
+ UID_RTStructureSetStorage,
+ UID_RTBeamsTreatmentRecordStorage,
+ UID_RTPlanStorage,
+ UID_RTBrachyTreatmentRecordStorage,
+ UID_RTTreatmentSummaryRecordStorage,
+ UID_RTIonPlanStorage,
+ UID_RTIonBeamsTreatmentRecordStorage,
+ UID_GenericImplantTemplateStorage,
+ UID_ImplantAssemblyTemplateStorage,
+ UID_ImplantTemplateGroupStorage
+ };
+
+ if(std::find(storage.begin(), storage.end(), sop_class_uid) != storage.end())
+ {
+ this->SCU::set_affected_sop_class(sop_class_uid);
+ }
+ else
+ {
+ throw Exception("Could not guess affected SOP class from dataset");
+ }
+}
+
+void
+StoreSCU
+::store(DataSet const & dataset, ProgressCallback callback, void * data) const
+{
+ CStoreRequest const request(
+ this->_association->get_association()->nextMsgID++,
+ this->_affected_sop_class,
+ dataset.as_string(registry::SOPInstanceUID, 0),
+ Message::Priority::MEDIUM,
+ dataset);
+ this->_send(request, this->_affected_sop_class, callback, data);
+
+ CStoreResponse const response = this->_receive<CStoreResponse>();
+
+ if(response.get_message_id_being_responded_to() != request.get_message_id())
+ {
+ std::ostringstream message;
+ message << "DIMSE: Unexpected Response MsgId: "
+ << response.get_message_id_being_responded_to()
+ << "(expected: " << request.get_message_id() << ")";
+ throw Exception(message.str());
+ }
+
+ if(response.has_affected_sop_class_uid() &&
+ response.get_affected_sop_class_uid() != request.get_affected_sop_class_uid())
+ {
+ std::ostringstream message;
+ message << "DIMSE: Unexpected Response Affected SOP Class UID: "
+ << response.get_affected_sop_class_uid()
+ << " (expected: " << request.get_affected_sop_class_uid() << ")";
+ throw Exception(message.str());
+ }
+ if(response.has_affected_sop_instance_uid() &&
+ response.get_affected_sop_instance_uid() != request.get_affected_sop_instance_uid())
+ {
+ std::ostringstream message;
+ message << "DIMSE: Unexpected Response Affected SOP Instance UID: "
+ << response.get_affected_sop_instance_uid()
+ << " (expected: " << request.get_affected_sop_instance_uid() << ")";
+ throw Exception(message.str());
+ }
+}
+
+}
diff --git a/src/dcmtkpp/StoreSCU.h b/src/dcmtkpp/StoreSCU.h
new file mode 100644
index 0000000..d805a73
--- /dev/null
+++ b/src/dcmtkpp/StoreSCU.h
@@ -0,0 +1,36 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _1b2f876e_1ad2_464d_9423_28181320aed0
+#define _1b2f876e_1ad2_464d_9423_28181320aed0
+
+#include "SCU.h"
+
+#include "dcmtkpp/DataSet.h"
+
+namespace dcmtkpp
+{
+
+/// @brief SCU for C-Store services.
+class StoreSCU: public SCU
+{
+public:
+ /// @brief Destructor.
+ virtual ~StoreSCU();
+
+ /// @brief Set the affected SOP class based on the dataset.
+ void set_affected_sop_class(DataSet const & dataset);
+
+ /// @brief Perform the C-STORE using an optional callback.
+ void store(DataSet const & dataset,
+ ProgressCallback callback=NULL, void * data=NULL) const;
+};
+
+}
+
+#endif // _1b2f876e_1ad2_464d_9423_28181320aed0
diff --git a/src/dcmtkpp/Tag.cpp b/src/dcmtkpp/Tag.cpp
new file mode 100644
index 0000000..c142a52
--- /dev/null
+++ b/src/dcmtkpp/Tag.cpp
@@ -0,0 +1,198 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/Tag.h"
+
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+#include <string>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcdicent.h>
+#include <dcmtk/dcmdata/dcdict.h>
+#include <dcmtk/dcmdata/dctagkey.h>
+
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+Tag
+::Tag(uint16_t group, uint16_t element)
+: group(group), element(element)
+{
+ // Nothing else
+}
+
+Tag
+::Tag(uint32_t tag)
+: group(tag >> 16), element(tag & 0xffff)
+{
+ // Nothing else
+}
+
+Tag
+::Tag(std::string const & string)
+{
+ this->_from_string(string);
+}
+
+Tag
+::Tag(char const * string)
+{
+ this->_from_string(string);
+}
+
+bool
+Tag
+::is_private() const
+{
+ return (this->group%2 == 1);
+}
+
+std::string
+Tag
+::get_name() const
+{
+ DcmTagKey const tag(this->group, this->element);
+ DcmDictEntry const * entry = dcmDataDict.rdlock().findEntry(tag, NULL);
+ if(entry == NULL)
+ {
+ throw Exception("No such element");
+ }
+
+ return entry->getTagName();
+}
+
+bool
+Tag
+::operator==(Tag const & other) const
+{
+ return ((this->group == other.group) && (this->element == other.element));
+}
+
+bool
+Tag
+::operator!=(Tag const & other) const
+{
+ return !(*this == other);
+}
+
+bool
+Tag
+::operator<(Tag const & other) const
+{
+ return (
+ (this->group < other.group) ||
+ (this->group == other.group && this->element < other.element));
+}
+
+bool
+Tag
+::operator>(Tag const & other) const
+{
+ return (
+ (this->group > other.group) ||
+ (this->group == other.group && this->element > other.element));
+}
+
+bool
+Tag
+::operator<=(Tag const & other) const
+{
+ return !(*this > other);
+}
+
+bool
+Tag
+::operator>=(Tag const & other) const
+{
+ return !(*this < other);
+}
+
+void
+Tag
+::_from_string(std::string const & string)
+{
+ DcmDictEntry const * entry = dcmDataDict.rdlock().findEntry(string.c_str());
+ if(entry == NULL)
+ {
+ // Try with string form of numeric tag
+ uint16_t group;
+ uint16_t element;
+ bool parsed = true;
+
+ if(string.size() != 8)
+ {
+ parsed = false;
+ }
+ else
+ {
+ std::string const first = string.substr(0, 4);
+ char * endptr;
+ group = strtol(first.c_str(), &endptr, 16);
+ if(*endptr != '\0')
+ {
+ parsed = false;
+ }
+ else
+ {
+ std::string const second = string.substr(4, 4);
+ element = strtol(second.c_str(), &endptr, 16);
+ if(*endptr != '\0')
+ {
+ parsed = false;
+ }
+ }
+ }
+
+ if(!parsed)
+ {
+ throw Exception("No such element: "+string);
+ }
+ else
+ {
+ this->group = group;
+ this->element = element;
+ }
+ }
+ else
+ {
+ DcmTagKey const tag = entry->getKey();
+ this->group = tag.getGroup();
+ this->element = tag.getElement();
+ }
+}
+
+Tag
+::operator std::string() const
+{
+ std::ostringstream stream;
+ stream << (*this);
+ return stream.str();
+}
+
+std::ostream & operator<<(std::ostream & stream, Tag const & tag)
+{
+ std::ostream::char_type const old_fill = stream.fill();
+ std::streamsize const old_width = stream.width();
+ std::ios::fmtflags const flags = stream.flags();
+
+ stream << std::hex
+ << std::setw(4) << std::setfill('0') << tag.group
+ << std::setw(4) << std::setfill('0') << tag.element;
+
+ stream.setf(flags);
+ stream.width(old_width);
+ stream.fill(old_fill);
+
+ return stream;
+}
+
+}
diff --git a/src/dcmtkpp/Tag.h b/src/dcmtkpp/Tag.h
new file mode 100644
index 0000000..12ec1d6
--- /dev/null
+++ b/src/dcmtkpp/Tag.h
@@ -0,0 +1,97 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _5faf4691_e936_476e_8ad3_40f36a167a74
+#define _5faf4691_e936_476e_8ad3_40f36a167a74
+
+#include <cstddef>
+#include <ostream>
+#include <string>
+
+namespace dcmtkpp
+{
+
+/**
+ * @brief A DICOM element tag.
+ */
+class Tag
+{
+public:
+ /// @brief Create a tag based on its group and element as two 16-bits words.
+ Tag(uint16_t group, uint16_t element);
+
+ /// @brief Create a tag based on its group and element as one 32-bits word.
+ Tag(uint32_t tag);
+
+ /**
+ * @brief Create a tag based on its name or string representation of its
+ * numeric value.
+ *
+ * If the name cannot be found in the public data dictionary, or if the
+ * string is not the representation of a numeric value, a dcmtkpp::Exception
+ * is raised.
+ */
+ Tag(std::string const & name);
+
+ /**
+ * @brief Create a tag based on its name or string representation of its
+ * numeric value.
+ *
+ * If the name cannot be found in the public data dictionary, or if the
+ * string is not the representation of a numeric value, a dcmtkpp::Exception
+ * is raised.
+ */
+ Tag(char const * name);
+
+ /// @brief Group of the tag.
+ uint16_t group;
+
+ /// @brief Element of the tag.
+ uint16_t element;
+
+ bool is_private() const;
+
+ /**
+ * @brief Return the name of the tag.
+ *
+ * If the tag cannot be found in the public data dictionary,
+ * a dcmtkpp::Exception is raised.
+ */
+ std::string get_name() const;
+
+ /// @brief Equality test.
+ bool operator==(Tag const & other) const;
+
+ /// @brief Difference test.
+ bool operator!=(Tag const & other) const;
+
+ /// @brief Strict inferiority test.
+ bool operator<(Tag const & other) const;
+
+ /// @brief Strict superiority test.
+ bool operator>(Tag const & other) const;
+
+ /// @brief Loose inferiority test.
+ bool operator<=(Tag const & other) const;
+
+ /// @brief Loose superiority test.
+ bool operator>=(Tag const & other) const;
+
+ /// @brief Convert to string
+ operator std::string() const;
+
+private:
+ void _from_string(std::string const & string);
+};
+
+/// @brief Stream inserter
+std::ostream & operator<<(std::ostream & stream, Tag const & tag);
+
+}
+
+#endif // _5faf4691_e936_476e_8ad3_40f36a167a74
diff --git a/src/dcmtkpp/VR.cpp b/src/dcmtkpp/VR.cpp
new file mode 100644
index 0000000..05b2a7f
--- /dev/null
+++ b/src/dcmtkpp/VR.cpp
@@ -0,0 +1,151 @@
+#include <dcmtkpp/VR.h>
+
+#include <map>
+#include <stdexcept>
+#include <string>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcdicent.h>
+#include <dcmtk/dcmdata/dcdict.h>
+#include <dcmtk/dcmdata/dctagkey.h>
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Tag.h"
+
+// Anonymous namespace, should not be publicly accessed
+namespace
+{
+
+#define ADD_TO_MAP(map, vr) map[dcmtkpp::VR::vr] = #vr
+
+std::map<dcmtkpp::VR, std::string>
+_build_enum_to_name()
+{
+ std::map<dcmtkpp::VR, std::string> result;
+ ADD_TO_MAP(result, AE);
+ ADD_TO_MAP(result, AS);
+ ADD_TO_MAP(result, AT);
+ ADD_TO_MAP(result, CS);
+ ADD_TO_MAP(result, DA);
+ ADD_TO_MAP(result, DS);
+ ADD_TO_MAP(result, DT);
+ ADD_TO_MAP(result, FL);
+ ADD_TO_MAP(result, FD);
+ ADD_TO_MAP(result, IS);
+ ADD_TO_MAP(result, LO);
+ ADD_TO_MAP(result, LT);
+ ADD_TO_MAP(result, PN);
+ ADD_TO_MAP(result, OB);
+ ADD_TO_MAP(result, OF);
+ ADD_TO_MAP(result, OW);
+ ADD_TO_MAP(result, SH);
+ ADD_TO_MAP(result, SL);
+ ADD_TO_MAP(result, SQ);
+ ADD_TO_MAP(result, SS);
+ ADD_TO_MAP(result, ST);
+ ADD_TO_MAP(result, TM);
+ ADD_TO_MAP(result, UC);
+ ADD_TO_MAP(result, UI);
+ ADD_TO_MAP(result, UL);
+ ADD_TO_MAP(result, UN);
+ ADD_TO_MAP(result, UR);
+ ADD_TO_MAP(result, US);
+ ADD_TO_MAP(result, UT);
+
+ return result;
+}
+
+#undef ADD_TO_MAP
+
+std::map<std::string, dcmtkpp::VR>
+_build_name_to_enum()
+{
+ std::map<dcmtkpp::VR, std::string> const enum_to_name = _build_enum_to_name();
+
+ std::map<std::string, dcmtkpp::VR> result;
+ for(std::map<dcmtkpp::VR, std::string>::const_iterator it = enum_to_name.begin();
+ it != enum_to_name.end(); ++it)
+ {
+ result[it->second] = it->first;
+ }
+
+ return result;
+}
+
+std::map<dcmtkpp::VR, std::string> const
+_enum_to_name = _build_enum_to_name();
+
+std::map<std::string, dcmtkpp::VR> const
+_name_to_enum = _build_name_to_enum();
+
+}
+
+namespace dcmtkpp
+{
+
+std::string as_string(VR vr)
+{
+ try
+ {
+ return _enum_to_name.at(vr);
+ }
+ catch(std::out_of_range const &)
+ {
+ throw Exception("Unknown VR");
+ }
+}
+
+VR as_vr(std::string const vr)
+{
+ try
+ {
+ return _name_to_enum.at(vr);
+ }
+ catch(std::out_of_range const &)
+ {
+ throw Exception("Unknown VR: "+vr);
+ }
+}
+
+VR as_vr(Tag const & tag)
+{
+ DcmTagKey const dcmtk_tag(tag.group, tag.element);
+ DcmDictEntry const * entry = dcmDataDict.rdlock().findEntry(dcmtk_tag, NULL);
+ if(entry == NULL)
+ {
+ throw Exception("No such element");
+ }
+
+ VR const vr(as_vr(std::string(entry->getVR().getValidVRName())));
+
+ return vr;
+}
+
+bool is_int(VR vr)
+{
+ return (
+ vr == VR::IS || vr == VR::SL || vr == VR::SS || vr == VR::UL ||
+ vr == VR::US);
+}
+
+bool is_real(VR vr)
+{
+ return (vr == VR::DS || vr == VR::FL || vr == VR::FD);
+}
+
+bool is_string(VR vr)
+{
+ return (
+ vr == VR::AE || vr == VR::AS || vr == VR::CS || vr == VR::DA ||
+ vr == VR::DT || vr == VR::LO || vr == VR::LT || vr == VR::PN ||
+ vr == VR::SH || vr == VR::ST || vr == VR::TM || vr == VR::UC ||
+ vr == VR::UI || vr == VR::UR || vr == VR::UT);
+}
+
+bool is_binary(VR vr)
+{
+ return (vr == VR::OB || vr == VR::OF || vr == VR::OW || vr == VR::UN);
+}
+
+
+}
diff --git a/src/dcmtkpp/VR.h b/src/dcmtkpp/VR.h
new file mode 100644
index 0000000..f60b4b0
--- /dev/null
+++ b/src/dcmtkpp/VR.h
@@ -0,0 +1,59 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _998aa43a_9e90_4d39_a074_a7074ac5c9b8
+#define _998aa43a_9e90_4d39_a074_a7074ac5c9b8
+
+#include <string>
+
+namespace dcmtkpp
+{
+
+class Tag;
+
+/// @brief Value representations of DICOM.
+enum class VR
+{
+ UNKNOWN,
+ AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, PN, OB, OF, OW, SH, SL,
+ SQ, SS, ST, TM, UC, UI, UL, UN, UR, US, UT,
+ INVALID
+};
+
+/// @brief Convert a VR to its string representation.
+std::string as_string(VR vr);
+
+/**
+ * @brief Convert a string to its VR.
+ *
+ * If the string does not represent a VR, a dcmtkpp::Exception is raised.
+ */
+VR as_vr(std::string const vr);
+
+/**
+ * @brief Guess a VR from a tag.
+ *
+ * If the VR cannot be guessed, a dcmtkpp::Exception is raised.
+ */
+VR as_vr(Tag const & tag);
+
+/// @brief Test whether a VR contains integers.
+bool is_int(VR vr);
+
+/// @brief Test whether a VR contains rel numbers.
+bool is_real(VR vr);
+
+/// @brief Test whether a VR contains text.
+bool is_string(VR vr);
+
+/// @brief Test whether a VR contains binary data.
+bool is_binary(VR vr);
+
+}
+
+#endif // _998aa43a_9e90_4d39_a074_a7074ac5c9b8
diff --git a/src/dcmtkpp/VRTraits.h b/src/dcmtkpp/VRTraits.h
new file mode 100644
index 0000000..feb3491
--- /dev/null
+++ b/src/dcmtkpp/VRTraits.h
@@ -0,0 +1,66 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _4f556093_02e3_4659_9026_2b16bc2c8a51
+#define _4f556093_02e3_4659_9026_2b16bc2c8a51
+
+namespace dcmtkpp
+{
+
+/**
+ * @class dcmtkpp::VRTraits
+ * @brief Information related to VR.
+ *
+ * The members are:
+ * - ValueType: the DCMTK type of the VR
+ */
+template<DcmEVR VR>
+struct VRTraits;
+
+#define DECLARE_VR_TRAITS(vr, value_type) \
+/** @brief Traits for generic data access to values of DcmElement. */ \
+template<> \
+struct VRTraits<vr> \
+{ \
+ /** @brief Type associated to the VR. */ \
+ typedef value_type ValueType; \
+};
+
+DECLARE_VR_TRAITS(EVR_AE, std::string)
+DECLARE_VR_TRAITS(EVR_AS, std::string)
+//DECLARE_VR_TRAITS(EVR_AT
+DECLARE_VR_TRAITS(EVR_CS, std::string)
+DECLARE_VR_TRAITS(EVR_DA, std::string)
+DECLARE_VR_TRAITS(EVR_DS, Float64)
+DECLARE_VR_TRAITS(EVR_DT, std::string)
+DECLARE_VR_TRAITS(EVR_FD, Float64)
+DECLARE_VR_TRAITS(EVR_FL, Float32)
+DECLARE_VR_TRAITS(EVR_IS, Sint32)
+DECLARE_VR_TRAITS(EVR_LO, std::string)
+DECLARE_VR_TRAITS(EVR_LT, std::string)
+DECLARE_VR_TRAITS(EVR_OB, std::vector<unsigned char>)
+DECLARE_VR_TRAITS(EVR_OF, std::vector<unsigned char>)
+DECLARE_VR_TRAITS(EVR_OW, std::vector<unsigned char>)
+DECLARE_VR_TRAITS(EVR_PN, std::string)
+DECLARE_VR_TRAITS(EVR_SH, std::string)
+DECLARE_VR_TRAITS(EVR_SL, Sint32)
+//DECLARE_VR_TRAITS(EVR_SQ
+DECLARE_VR_TRAITS(EVR_SS, Sint16)
+DECLARE_VR_TRAITS(EVR_ST, std::string)
+DECLARE_VR_TRAITS(EVR_TM, std::string)
+DECLARE_VR_TRAITS(EVR_UI, std::string)
+DECLARE_VR_TRAITS(EVR_UL, Uint32)
+DECLARE_VR_TRAITS(EVR_UN, std::vector<unsigned char>)
+DECLARE_VR_TRAITS(EVR_US, Uint16)
+DECLARE_VR_TRAITS(EVR_UT, std::string)
+
+#undef DECLARE_VR_TRAITS
+
+}
+
+#endif // _4f556093_02e3_4659_9026_2b16bc2c8a51
diff --git a/src/dcmtkpp/Value.cpp b/src/dcmtkpp/Value.cpp
new file mode 100644
index 0000000..6bac089
--- /dev/null
+++ b/src/dcmtkpp/Value.cpp
@@ -0,0 +1,196 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/Value.h"
+
+#include <cstdint>
+#include <initializer_list>
+#include <string>
+#include <vector>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+Value
+::Value()
+: _type(Type::Empty)
+{
+ // Nothing else.
+}
+
+Value
+::Value(Integers const & integers)
+: _type(Type::Integers), _integers(integers)
+{
+ // Nothing else.
+}
+
+Value
+::Value(Reals const & reals)
+: _type(Type::Reals), _reals(reals)
+{
+ // Nothing else.
+}
+
+Value
+::Value(Strings const & strings)
+: _type(Type::Strings), _strings(strings)
+{
+ // Nothing else.
+}
+
+Value
+::Value(DataSets const & datasets)
+: _type(Type::DataSets), _data_sets(datasets)
+{
+ // Nothing else.
+}
+
+Value
+::Value(Binary const & binary)
+: _type(Type::Binary), _binary(binary)
+{
+ // Nothing else.
+}
+
+Value
+::Value(std::initializer_list<int> const & list)
+: _type(Type::Integers)
+{
+ this->_integers.resize(list.size());
+ std::copy(list.begin(), list.end(), this->_integers.begin());
+}
+
+Value
+::Value(std::initializer_list<Integer> const & list)
+: _type(Type::Integers), _integers(list)
+{
+ // Nothing else
+}
+
+Value
+::Value(std::initializer_list<Real> const & list)
+: _type(Type::Reals), _reals(list)
+{
+ // Nothing else
+}
+
+Value
+::Value(std::initializer_list<String> const & list)
+: _type(Type::Strings), _strings(list)
+{
+ // Nothing else
+}
+
+Value
+::Value(std::initializer_list<DataSet> const & list)
+: _type(Type::DataSets), _data_sets(list)
+{
+ // Nothing else
+}
+
+Value::Type
+Value
+::get_type() const
+{
+ return this->_type;
+}
+
+#define DECLARE_CONST_ACCESSOR(type, name) \
+Value::type const & \
+Value \
+::as_##name() const \
+{ \
+ if(this->get_type() != Type::type) \
+ { \
+ throw Exception("Type mismatch"); \
+ } \
+ return this->_##name; \
+}
+
+#define DECLARE_NON_CONST_ACCESSOR(type, name) \
+Value::type & \
+Value \
+::as_##name() \
+{ \
+ if(this->get_type() != Type::type) \
+ { \
+ throw Exception("Type mismatch"); \
+ } \
+ return this->_##name; \
+}
+
+DECLARE_CONST_ACCESSOR(Integers, integers)
+DECLARE_NON_CONST_ACCESSOR(Integers, integers)
+
+DECLARE_CONST_ACCESSOR(Reals, reals)
+DECLARE_NON_CONST_ACCESSOR(Reals, reals)
+
+DECLARE_CONST_ACCESSOR(Strings, strings)
+DECLARE_NON_CONST_ACCESSOR(Strings, strings)
+
+DECLARE_CONST_ACCESSOR(DataSets, data_sets)
+DECLARE_NON_CONST_ACCESSOR(DataSets, data_sets)
+
+DECLARE_CONST_ACCESSOR(Binary, binary)
+DECLARE_NON_CONST_ACCESSOR(Binary, binary)
+
+#undef DECLARE_NON_CONST_ACCESSOR
+#undef DECLARE_CONST_ACCESSOR
+
+bool
+Value
+::operator==(Value const & other) const
+{
+ if(this->_type != other._type)
+ {
+ return false;
+ }
+ else if(this->_type == Value::Type::Empty)
+ {
+ return true;
+ }
+ else if(this->_type == Value::Type::Integers)
+ {
+ return this->_integers == other._integers;
+ }
+ else if(this->_type == Value::Type::Reals)
+ {
+ return this->_reals == other._reals;
+ }
+ else if(this->_type == Value::Type::Strings)
+ {
+ return this->_strings == other._strings;
+ }
+ else if(this->_type == Value::Type::DataSets)
+ {
+ return this->_data_sets == other._data_sets;
+ }
+ else if(this->_type == Value::Type::Binary)
+ {
+ return this->_binary == other._binary;
+ }
+ else
+ {
+ throw Exception("Unknown type");
+ }
+}
+
+bool
+Value
+::operator!=(Value const & other) const
+{
+ return !(*this == other);
+}
+
+
+
+}
diff --git a/src/dcmtkpp/Value.h b/src/dcmtkpp/Value.h
new file mode 100644
index 0000000..5e7c1ed
--- /dev/null
+++ b/src/dcmtkpp/Value.h
@@ -0,0 +1,193 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _dca5b15b_b8df_4925_a446_d42efe06c923
+#define _dca5b15b_b8df_4925_a446_d42efe06c923
+
+#include <cstdint>
+#include <initializer_list>
+#include <string>
+#include <vector>
+
+namespace dcmtkpp
+{
+
+class DataSet;
+
+/**
+ * @brief A value held in a DICOM element.
+ */
+class Value
+{
+public:
+ /// @brief Possible types stored in the value.
+ enum class Type
+ {
+ Empty,
+ Integers,
+ Reals,
+ Strings,
+ DataSets,
+ Binary
+ };
+
+ typedef int64_t Integer;
+
+ typedef double Real;
+
+ typedef std::string String;
+
+ /// @brief Integer container.
+ typedef std::vector<Integer> Integers;
+
+ /// @brief Real container.
+ typedef std::vector<Real> Reals;
+
+ /// @brief String container.
+ typedef std::vector<String> Strings;
+
+ /// @brief Data sets container.
+ typedef std::vector<DataSet> DataSets;
+
+ /// @brief Binary data container.
+ typedef std::vector<uint8_t> Binary;
+
+ /// @brief Build an empty value.
+ Value();
+
+ /// @brief Build a value from integers.
+ Value(Integers const & integers);
+
+ /// @brief Build a value from reals.
+ Value(Reals const & reals);
+
+ /// @brief Build a value from strings.
+ Value(Strings const & strings);
+
+ /// @brief Build a value from data sets.
+ Value(DataSets const & datasets);
+
+ /// @brief Build a value from binary data.
+ Value(Binary const & binary);
+
+ /// @brief Build a value from integers.
+ Value(std::initializer_list<int> const & list);
+
+ /// @brief Build a value from integers.
+ Value(std::initializer_list<Integer> const & list);
+
+ /// @brief Build a value from reals.
+ Value(std::initializer_list<Real> const & list);
+
+ /// @brief Build a value from strings.
+ Value(std::initializer_list<String> const & list);
+
+ /// @brief Build a value from data sets.
+ Value(std::initializer_list<DataSet> const & list);
+
+ /// @brief Return the type store in the value.
+ Type get_type() const;
+
+ /**
+ * @brief Return the integers contained in the value.
+ *
+ * If the value does not contain integers, a dcmtkpp::Exception is raised.
+ */
+ Integers const & as_integers() const;
+
+ /**
+ * @brief Return the integers contained in the value.
+ *
+ * If the value does not contain integers, a dcmtkpp::Exception is raised.
+ */
+ Integers & as_integers();
+
+ /**
+ * @brief Return the reals contained in the value.
+ *
+ * If the value does not contain reals, a dcmtkpp::Exception is raised.
+ */
+ Reals const & as_reals() const;
+
+ /**
+ * @brief Return the reals contained in the value.
+ *
+ * If the value does not contain reals, a dcmtkpp::Exception is raised.
+ */
+ Reals & as_reals();
+
+ /**
+ * @brief Return the strings contained in the value.
+ *
+ * If the value does not contain strings, a dcmtkpp::Exception is raised.
+ */
+ Strings const & as_strings() const;
+
+ /**
+ * @brief Return the strings contained in the value.
+ *
+ * If the value does not contain strings, a dcmtkpp::Exception is raised.
+ */
+ Strings & as_strings();
+
+ /**
+ * @brief Return the data sets contained in the value.
+ *
+ * If the value does not contain data sets, a dcmtkpp::Exception is raised.
+ */
+ DataSets const & as_data_sets() const;
+
+ /**
+ * @brief Return the data sets contained in the value.
+ *
+ * If the value does not contain data sets, a dcmtkpp::Exception is raised.
+ */
+ DataSets & as_data_sets();
+
+ /**
+ * @brief Return the binary data contained in the value.
+ *
+ * If the value does not contain binary data, a dcmtkpp::Exception is raised.
+ */
+ Binary const & as_binary() const;
+
+ /**
+ * @brief Return the binary data contained in the value.
+ *
+ * If the value does not contain binary data, a dcmtkpp::Exception is raised.
+ */
+ Binary & as_binary();
+
+ /// @brief Equality test.
+ bool operator==(Value const & other) const;
+
+ /// @brief Difference test.
+ bool operator!=(Value const & other) const;
+
+private:
+ Integers _integers;
+ Reals _reals;
+ Strings _strings;
+ DataSets _data_sets;
+ Binary _binary;
+
+ Type _type;
+};
+
+/**
+ * @brief Visitor of values.
+ */
+template<typename TVisitor>
+typename TVisitor::result_type
+apply_visitor(TVisitor const & visitor, Value const & value);
+
+}
+
+#include "dcmtkpp/Value.txx"
+
+#endif // _dca5b15b_b8df_4925_a446_d42efe06c923
diff --git a/src/dcmtkpp/Value.txx b/src/dcmtkpp/Value.txx
new file mode 100644
index 0000000..55745c8
--- /dev/null
+++ b/src/dcmtkpp/Value.txx
@@ -0,0 +1,54 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _de64b8e1_4116_41f8_a085_dabfdc6c63c3
+#define _de64b8e1_4116_41f8_a085_dabfdc6c63c3
+
+#include "dcmtkpp/Value.h"
+
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+template<typename TVisitor>
+typename TVisitor::result_type
+apply_visitor(TVisitor const & visitor, Value const & value)
+{
+ if(value.get_type() == Value::Type::Empty)
+ {
+ throw Exception("Empty value");
+ }
+ else if(value.get_type() == Value::Type::Integers)
+ {
+ return visitor(value.as_integers());
+ }
+ else if(value.get_type() == Value::Type::Reals)
+ {
+ return visitor(value.as_reals());
+ }
+ else if(value.get_type() == Value::Type::Strings)
+ {
+ return visitor(value.as_strings());
+ }
+ else if(value.get_type() == Value::Type::DataSets)
+ {
+ return visitor(value.as_data_sets());
+ }
+ else if(value.get_type() == Value::Type::Binary)
+ {
+ return visitor(value.as_binary());
+ }
+ else
+ {
+ throw Exception("Unknown value type");
+ }
+}
+
+}
+
+#endif // _de64b8e1_4116_41f8_a085_dabfdc6c63c3
diff --git a/src/dcmtkpp/conversion.cpp b/src/dcmtkpp/conversion.cpp
new file mode 100644
index 0000000..d1da178
--- /dev/null
+++ b/src/dcmtkpp/conversion.cpp
@@ -0,0 +1,485 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/conversion.h"
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dctk.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Element.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Tag.h"
+#include "dcmtkpp/VR.h"
+
+namespace dcmtkpp
+{
+
+DcmEVR convert(VR vr)
+{
+ if(vr == VR::AE) { return EVR_AE; }
+ else if(vr == VR::AS) { return EVR_AS; }
+ else if(vr == VR::AT) { return EVR_AT; }
+ else if(vr == VR::CS) { return EVR_CS; }
+ else if(vr == VR::DA) { return EVR_DA; }
+ else if(vr == VR::DS) { return EVR_DS; }
+ else if(vr == VR::DT) { return EVR_DT; }
+ else if(vr == VR::FL) { return EVR_FL; }
+ else if(vr == VR::FD) { return EVR_FD; }
+ else if(vr == VR::IS) { return EVR_IS; }
+ else if(vr == VR::LO) { return EVR_LO; }
+ else if(vr == VR::LT) { return EVR_LT; }
+ else if(vr == VR::OB) { return EVR_OB; }
+ else if(vr == VR::OF) { return EVR_OF; }
+ else if(vr == VR::OW) { return EVR_OW; }
+ else if(vr == VR::PN) { return EVR_PN; }
+ else if(vr == VR::SH) { return EVR_SH; }
+ else if(vr == VR::SL) { return EVR_SL; }
+ else if(vr == VR::SQ) { return EVR_SQ; }
+ else if(vr == VR::SS) { return EVR_SS; }
+ else if(vr == VR::ST) { return EVR_ST; }
+ else if(vr == VR::TM) { return EVR_TM; }
+ else if(vr == VR::UI) { return EVR_UI; }
+ else if(vr == VR::UL) { return EVR_UL; }
+ else if(vr == VR::UN) { return EVR_UN; }
+ else if(vr == VR::US) { return EVR_US; }
+ else if(vr == VR::UT) { return EVR_UT; }
+ else
+ {
+ throw Exception("Unknown VR");
+ }
+}
+
+VR convert(DcmEVR evr)
+{
+ if(evr == EVR_AE) { return VR::AE; }
+ else if(evr == EVR_AS) { return VR::AS; }
+ else if(evr == EVR_AT) { return VR::AT; }
+ else if(evr == EVR_CS) { return VR::CS; }
+ else if(evr == EVR_DA) { return VR::DA; }
+ else if(evr == EVR_DS) { return VR::DS; }
+ else if(evr == EVR_DT) { return VR::DT; }
+ else if(evr == EVR_FL) { return VR::FL; }
+ else if(evr == EVR_FD) { return VR::FD; }
+ else if(evr == EVR_IS) { return VR::IS; }
+ else if(evr == EVR_LO) { return VR::LO; }
+ else if(evr == EVR_LT) { return VR::LT; }
+ else if(evr == EVR_OB) { return VR::OB; }
+ else if(evr == EVR_OF) { return VR::OF; }
+ else if(evr == EVR_OW) { return VR::OW; }
+ else if(evr == EVR_PN) { return VR::PN; }
+ else if(evr == EVR_SH) { return VR::SH; }
+ else if(evr == EVR_SL) { return VR::SL; }
+ else if(evr == EVR_SQ) { return VR::SQ; }
+ else if(evr == EVR_SS) { return VR::SS; }
+ else if(evr == EVR_ST) { return VR::ST; }
+ else if(evr == EVR_TM) { return VR::TM; }
+ else if(evr == EVR_UI) { return VR::UI; }
+ else if(evr == EVR_UL) { return VR::UL; }
+ else if(evr == EVR_UN) { return VR::UN; }
+ else if(evr == EVR_US) { return VR::US; }
+ else if(evr == EVR_UT) { return VR::UT; }
+ else
+ {
+ throw Exception("Unknown VR");
+ }
+}
+
+DcmTagKey convert(Tag const & tag)
+{
+ return DcmTagKey(tag.group, tag.element);
+}
+
+Tag convert(DcmTagKey const & tag)
+{
+ return Tag(tag.getGroup(), tag.getElement());
+}
+
+DcmElement * convert(const Tag & tag, Element const & source)
+{
+ DcmTag const destination_tag(convert(tag), convert(source.vr));
+
+ DcmElement * destination = NULL;
+ if(source.vr == VR::AE)
+ {
+ destination = new DcmApplicationEntity(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::AS)
+ {
+ destination = new DcmAgeString(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if(source.vr == VR::AT)
+ {
+ destination = new DcmAttributeTag(destination_tag);
+ if(!source.empty())
+ {
+ for(unsigned int i=0; i<source.as_string().size(); ++i)
+ {
+ Tag const source_tag(source.as_string()[i]);
+ DcmTagKey const destination_tag = convert(source_tag);
+ destination->putTagVal(destination_tag, i);
+ }
+ }
+ }
+ else if (source.vr == VR::CS)
+ {
+ destination = new DcmCodeString(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::DA)
+ {
+ destination = new DcmDate(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::DS)
+ {
+ destination = new DcmDecimalString(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Reals>(source, destination, &Element::as_real);
+ }
+ }
+ else if (source.vr == VR::DT)
+ {
+ destination = new DcmDateTime(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::FD)
+ {
+ destination = new DcmFloatingPointDouble(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Reals, Float64>(source, destination, &Element::as_real);
+ }
+ }
+ else if (source.vr == VR::FL)
+ {
+ destination = new DcmFloatingPointSingle(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Reals, Float32>(source, destination, &Element::as_real);
+ }
+ }
+ else if (source.vr == VR::IS)
+ {
+ destination = new DcmIntegerString(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Integers>(source, destination, &Element::as_int);
+ }
+ }
+ else if (source.vr == VR::LO)
+ {
+ destination = new DcmLongString(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::LT)
+ {
+ destination = new DcmLongText(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::OB || source.vr == VR::OW)
+ {
+ destination = new DcmOtherByteOtherWord(destination_tag);
+ if(!source.empty())
+ {
+ convert(source, static_cast<DcmOtherByteOtherWord*>(destination));
+ }
+ }
+ // OF
+ else if (source.vr == VR::PN)
+ {
+ destination = new DcmPersonName(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::SH)
+ {
+ destination = new DcmShortString(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::SL)
+ {
+ destination = new DcmSignedLong(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Integers, Sint32>(source, destination, &Element::as_int);
+ }
+ }
+ else if(source.vr == VR::SQ)
+ {
+ DcmSequenceOfItems * sequence = new DcmSequenceOfItems(destination_tag);
+ if(!source.empty())
+ {
+ for(auto const & source_item: source.as_data_set())
+ {
+ DcmItem * destination_item = convert(source_item);
+ sequence->append(destination_item);
+ }
+ }
+ destination = sequence;
+ }
+ else if (source.vr == VR::SS)
+ {
+ destination = new DcmSignedShort(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Integers, Sint16>(source, destination, &Element::as_int);
+ }
+ }
+ else if (source.vr == VR::ST)
+ {
+ destination = new DcmShortText(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::TM)
+ {
+ destination = new DcmTime(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::UI)
+ {
+ destination = new DcmUniqueIdentifier(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else if (source.vr == VR::UL)
+ {
+ destination = new DcmUnsignedLong(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Integers, Uint32>(source, destination, &Element::as_int);
+ }
+ }
+ // UN
+ else if (source.vr == VR::US)
+ {
+ destination = new DcmUnsignedShort(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Integers, Uint16>(source, destination, &Element::as_int);
+ }
+ }
+ else if (source.vr == VR::UT)
+ {
+ destination = new DcmUnlimitedText(destination_tag);
+ if(!source.empty())
+ {
+ convert<Value::Strings>(source, destination, &Element::as_string);
+ }
+ }
+ else
+ {
+ throw Exception("Unknown VR");
+ }
+
+ return destination;
+}
+
+template<>
+void convert<std::vector<uint8_t>, Value::Binary>(
+ DcmElement * source, Element & destination,
+ Value::Binary & (Element::*getter)())
+{
+ auto & destination_values = (destination.*getter)();
+ destination_values =
+ dcmtkpp::ElementAccessor<std::vector<uint8_t>>::element_get(*source, 0);
+}
+
+Element convert(DcmElement * source)
+{
+ Element destination;
+
+ DcmEVR const source_vr = source->getTag().getVR().getValidEVR();
+ VR const destination_vr = convert(source_vr);
+
+ if(source_vr == EVR_AE || source_vr == EVR_AS || source_vr == EVR_CS ||
+ source_vr == EVR_DA || source_vr == EVR_DT || source_vr == EVR_LO ||
+ source_vr == EVR_LT || source_vr == EVR_PN || source_vr == EVR_SH ||
+ source_vr == EVR_ST || source_vr == EVR_TM || source_vr == EVR_UI ||
+ source_vr == EVR_UT)
+ {
+ destination = Element(Value::Strings(), destination_vr);
+ convert<std::string, Value::Strings>(source, destination, &Element::as_string);
+ }
+ else if(source_vr == EVR_AT)
+ {
+ destination = Element(Value::Strings(), destination_vr);
+ destination.as_string().reserve(source->getVM());
+ for(unsigned int i=0; i<source->getVM(); ++i)
+ {
+ DcmTagKey source_tag;
+ OFCondition const condition = source->getTagVal(source_tag, i);
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+ Tag const destination_tag = convert(source_tag);
+ destination.as_string().push_back(std::string(destination_tag));
+ }
+ }
+ else if(source_vr == EVR_DS || source_vr == EVR_FD)
+ {
+ destination = Element(Value::Reals(), destination_vr);
+ convert<Float64, Value::Reals>(source, destination, &Element::as_real);
+ }
+ else if(source_vr == EVR_FL)
+ {
+ destination = Element(Value::Reals(), destination_vr);
+ convert<Float32, Value::Reals>(source, destination, &Element::as_real);
+ }
+ else if(source_vr == EVR_IS || source_vr == EVR_SL)
+ {
+ destination = Element(Value::Integers(), destination_vr);
+ convert<Sint32, Value::Integers>(source, destination, &Element::as_int);
+ }
+ else if(source_vr == EVR_SQ)
+ {
+ destination = Element(Value::DataSets(), destination_vr);
+ DcmSequenceOfItems * sequence = dynamic_cast<DcmSequenceOfItems*>(source);
+ if(sequence == NULL)
+ {
+ throw Exception("Element is not a DcmSequenceOfItems");
+ }
+
+ Value::DataSets & destination_value = destination.as_data_set();
+
+ destination_value.reserve(sequence->card());
+ for(unsigned int i=0; i<sequence->card(); ++i)
+ {
+ DcmItem * source_item = sequence->getItem(i);
+ DataSet const destination_item = convert(source_item);
+ destination_value.push_back(destination_item);
+ }
+ }
+ else if(source_vr == EVR_SS)
+ {
+ destination = Element(Value::Integers(), destination_vr);
+ convert<Sint16, Value::Integers>(source, destination, &Element::as_int);
+ }
+ else if(source_vr == EVR_UL)
+ {
+ destination = Element(Value::Integers(), destination_vr);
+ convert<Uint32, Value::Integers>(source, destination, &Element::as_int);
+ }
+ else if(source_vr == EVR_OB || source_vr == EVR_OF || source_vr == EVR_OW ||
+ source_vr == EVR_UN)
+ {
+ destination = Element(Value::Binary(), destination_vr);
+ convert<std::vector<uint8_t>, Value::Binary>(source, destination, &Element::as_binary);
+ }
+ else if(source_vr == EVR_US)
+ {
+ destination = Element(Value::Integers(), destination_vr);
+ convert<Uint16, Value::Integers>(source, destination, &Element::as_int);
+ }
+ else
+ {
+ throw Exception("Unknown VR");
+ }
+
+ return destination;
+}
+
+void convert(Element const & source, DcmOtherByteOtherWord * destination)
+{
+ auto const & value = source.as_binary();
+
+ Uint8 * output;
+ OFCondition condition;
+ if(destination->getTag().getVR().getValidEVR() == EVR_OB)
+ {
+ condition = destination->createUint8Array(source.size(), output);
+ }
+ else
+ {
+ Uint16* temp;
+ condition = destination->createUint16Array(source.size()/2, temp);
+ output = reinterpret_cast<Uint8*>(temp);
+ }
+
+ if(condition.bad())
+ {
+ throw Exception(condition);
+ }
+
+ std::copy(value.begin(), value.end(), output);
+}
+
+void convert(Element const & source, DcmOtherFloat * destination)
+{
+ auto const & value = source.as_binary();
+}
+
+DcmItem * convert(DataSet const & source)
+{
+ DcmDataset * destination = new DcmDataset();
+
+ for(auto const & iterator: source)
+ {
+ auto const destination_element = convert(
+ iterator.first, iterator.second);
+ destination->insert(destination_element);
+ }
+
+ return destination;
+}
+
+DataSet convert(DcmItem * source)
+{
+ DataSet destination;
+
+ for(unsigned long i=0; i<source->card(); ++i)
+ {
+ auto const source_element = source->getElement(i);
+
+ auto const destination_tag = convert(source_element->getTag());
+ auto const destination_element = convert(source_element);
+
+ destination.add(destination_tag, destination_element);
+ }
+ return destination;
+}
+
+}
diff --git a/src/dcmtkpp/conversion.h b/src/dcmtkpp/conversion.h
new file mode 100644
index 0000000..b39bf9a
--- /dev/null
+++ b/src/dcmtkpp/conversion.h
@@ -0,0 +1,72 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _d5ecacb8_04ff_48b0_8026_570c9b2ae360
+#define _d5ecacb8_04ff_48b0_8026_570c9b2ae360
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dctk.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Element.h"
+#include "dcmtkpp/Tag.h"
+#include "dcmtkpp/VR.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Convert a dcmtkpp::VR to a DcmVR.
+DcmEVR convert(VR vr);
+
+/// @brief Convert a DcmVR to a dcmtkpp::VR.
+VR convert(DcmEVR evr);
+
+/// @brief Convert a dcmtkpp::Tag to a DcmTagKey.
+DcmTagKey convert(Tag const & tag);
+
+/// @brief Convert a DcmTagKey to a dcmtkpp::Tag.
+Tag convert(DcmTagKey const & tag);
+
+/// @brief Convert a dcmtkpp::Element to a DcmElement.
+DcmElement * convert(Tag const & tag, Element const & source);
+
+/// @brief Low-level element converter.
+template<typename TSourceType, typename TDestinationType>
+void convert(
+ Element const & source, DcmElement * destination,
+ TSourceType const & (Element::*getter)() const);
+
+/// @brief Convert a DcmElement to a dcmtkpp::Element.
+Element convert(DcmElement * source);
+
+/// @brief Low-level element converter.
+template<typename TSourceType>
+void convert(
+ Element const & source, DcmElement * destination,
+ TSourceType const & (Element::*getter)() const);
+
+/// @brief Low-level element converver.
+void convert(Element const & source, DcmOtherByteOtherWord * destination);
+
+/// @brief Low-level element converter.
+template<typename TSourceType, typename TDestinationType>
+void convert(
+ DcmElement * source, Element & destination,
+ TDestinationType & (Element::*getter)());
+
+/// @brief Convert a dcmtkpp::DataSet to a DcmDataset.
+DcmItem * convert(DataSet const & source);
+
+/// @brief Convert a DcmDataset to a dcmtkpp::DataSet.
+DataSet convert(DcmItem * source);
+
+}
+
+#include <dcmtkpp/conversion.txx>
+
+#endif // _d5ecacb8_04ff_48b0_8026_570c9b2ae360
diff --git a/src/dcmtkpp/conversion.txx b/src/dcmtkpp/conversion.txx
new file mode 100644
index 0000000..0c296eb
--- /dev/null
+++ b/src/dcmtkpp/conversion.txx
@@ -0,0 +1,82 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _665b5269_140c_4320_94f2_ad8a7c052e9b
+#define _665b5269_140c_4320_94f2_ad8a7c052e9b
+
+#include "dcmtkpp/conversion.h"
+
+#include <sstream>
+
+#include "dcmtkpp/Element.h"
+#include "dcmtkpp/ElementAccessor.h"
+
+namespace dcmtkpp
+{
+
+template<typename TSourceType, typename TDestinationType>
+void convert(
+ Element const & source, DcmElement * destination,
+ TSourceType const & (Element::*getter)() const)
+{
+ auto const & source_values = (source.*getter)();
+ for(auto i = 0; i<source_values.size(); ++i)
+ {
+ ElementAccessor<TDestinationType>::element_set(
+ *destination, source_values[i], i);
+ }
+}
+
+template<typename TSourceType>
+void convert(
+ Element const & source, DcmElement * destination,
+ TSourceType const & (Element::*getter)() const)
+{
+ OFString destination_value;
+
+ auto const & source_values = (source.*getter)();
+ if(!source_values.empty())
+ {
+ auto const last_it = --source_values.end();
+ auto it = source_values.begin();
+ while(it != last_it)
+ {
+ std::ostringstream stream;
+ stream << *it;
+ destination_value += stream.str().c_str();
+ destination_value += "\\";
+ ++it;
+ }
+
+ std::ostringstream stream;
+ stream << *last_it;
+ destination_value += stream.str().c_str();
+ }
+
+ destination->putOFStringArray(destination_value);
+}
+
+template<typename TSourceType, typename TDestinationType>
+void convert(
+ DcmElement * source, Element & destination,
+ TDestinationType & (Element::*getter)())
+{
+ auto & destination_values = (destination.*getter)();
+
+ destination_values.reserve(source->getVM());
+
+ for(auto i = 0; i<source->getVM(); ++i)
+ {
+ destination_values.push_back(
+ dcmtkpp::ElementAccessor<TSourceType>::element_get(*source, i));
+ }
+}
+
+}
+
+#endif // _665b5269_140c_4320_94f2_ad8a7c052e9b
diff --git a/src/dcmtkpp/json_converter.cpp b/src/dcmtkpp/json_converter.cpp
new file mode 100644
index 0000000..ac53f04
--- /dev/null
+++ b/src/dcmtkpp/json_converter.cpp
@@ -0,0 +1,280 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/json_converter.h"
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/ofstd/ofstd.h>
+#include <dcmtk/ofstd/ofstream.h>
+#include <jsoncpp/json/json.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Value.h"
+#include "dcmtkpp/VR.h"
+
+namespace dcmtkpp
+{
+
+struct ToJSONVisitor
+{
+ typedef Json::Value result_type;
+
+ result_type operator()(VR const vr) const
+ {
+ result_type result;
+
+ result["vr"] = as_string(vr);
+
+ return result;
+ }
+
+ template<typename T>
+ result_type operator()(VR const vr, T const & value) const
+ {
+ result_type result;
+
+ result["vr"] = as_string(vr);
+
+ for(auto const & item: value)
+ {
+ result["Value"].append(item);
+ }
+
+ return result;
+ }
+
+ result_type operator()(VR const vr, Value::Integers const & value) const
+ {
+ result_type result;
+
+ result["vr"] = as_string(vr);
+
+ for(auto const & item: value)
+ {
+ result["Value"].append(Json::Int64(item));
+ }
+ return result;
+ }
+
+ result_type operator()(VR const vr, Value::Strings const & value) const
+ {
+ result_type result;
+
+ result["vr"] = as_string(vr);
+
+ if(vr == VR::PN)
+ {
+ auto const fields = { "Alphabetic", "Ideographic", "Phonetic" };
+
+ for(auto const item: value)
+ {
+ auto fields_it = fields.begin();
+
+ Json::Value json_item;
+
+ std::string::size_type begin=0;
+ while(begin != std::string::npos)
+ {
+ std::string::size_type const end = item.find("=", begin);
+
+ std::string::size_type size = 0;
+ if(end != std::string::npos)
+ {
+ size = end-begin;
+ }
+ else
+ {
+ size = std::string::npos;
+ }
+
+ json_item[*fields_it] = item.substr(begin, size);
+
+ if(end != std::string::npos)
+ {
+ begin = end+1;
+ ++fields_it;
+ if(fields_it == fields.end())
+ {
+ throw Exception("Invalid Person Name");
+ }
+ }
+ else
+ {
+ begin = end;
+ }
+ }
+ result["Value"].append(json_item);
+ }
+ }
+ else
+ {
+ for(auto const & item: value)
+ {
+ result["Value"].append(item);
+ }
+ }
+ return result;
+ }
+
+ result_type operator()(VR const vr, Value::DataSets const & value) const
+ {
+ result_type result;
+
+ result["vr"] = as_string(vr);
+
+ for(auto const & item: value)
+ {
+ result["Value"].append(as_json(item));
+ }
+ return result;
+ }
+
+ result_type operator()(VR const vr, Value::Binary const & value) const
+ {
+ result_type result;
+
+ result["vr"] = as_string(vr);
+
+ unsigned char const * data =
+ reinterpret_cast<unsigned char const *>(&value[0]);
+ OFStringStream stream;
+ OFStandard::encodeBase64(stream, data, value.size());
+ result["InlineBinary"] = stream.str().c_str();
+
+ return result;
+ }
+
+};
+
+Json::Value as_json(DataSet const & data_set)
+{
+ Json::Value json;
+
+ for(auto const & it: data_set)
+ {
+ auto const & tag = it.first;
+ auto const & element = it.second;
+
+ std::string const key(tag);
+ auto const value = apply_visitor(ToJSONVisitor(), element);
+ json[key] = value;
+ }
+
+ return json;
+}
+
+DataSet as_dataset(Json::Value const & json)
+{
+ DataSet data_set;
+
+ for(Json::Value::const_iterator it=json.begin(); it != json.end(); ++it)
+ {
+ Tag const tag(it.memberName());
+
+ Json::Value const & json_element = *it;
+ VR const vr = as_vr(json_element["vr"].asString());
+
+ Element element;
+
+ if(vr == VR::AE || vr == VR::AS || vr == VR::AT || vr == VR::CS ||
+ vr == VR::DA || vr == VR::DT || vr == VR::LO || vr == VR::LT ||
+ vr == VR::SH || vr == VR::ST || vr == VR::TM || vr == VR::UI ||
+ vr == VR::UT)
+ {
+ element = Element(Value::Strings(), vr);
+
+ auto const & json_value = json_element["Value"];
+ for(auto const & json_item: json_value)
+ {
+ element.as_string().push_back(json_item.asString());
+ }
+ }
+ else if(vr == VR::PN)
+ {
+ element = Element(Value::Strings(), vr);
+ auto const & json_value = json_element["Value"];
+ for(auto const & json_item: json_value)
+ {
+ Value::Strings::value_type dicom_item;
+ auto const fields = { "Alphabetic", "Ideographic", "Phonetic" };
+ for(auto const & field: fields)
+ {
+ if(json_item.isMember(field))
+ {
+ dicom_item += json_item[field].asString();
+ }
+ dicom_item += "=";
+ }
+
+ while(*dicom_item.rbegin() == '=')
+ {
+ dicom_item = dicom_item.substr(0, dicom_item.size()-1);
+ }
+
+ element.as_string().push_back(dicom_item);
+ }
+ }
+ else if(vr == VR::DS || vr == VR::FD || vr == VR::FL)
+ {
+ element = Element(Value::Reals(), vr);
+
+ auto const & json_value = json_element["Value"];
+ for(auto const & json_item: json_value)
+ {
+ element.as_real().push_back(json_item.asDouble());
+ }
+ }
+ else if(vr == VR::IS || vr == VR::SL || vr == VR::SS ||
+ vr == VR::UL || vr == VR::US)
+ {
+ element = Element(Value::Integers(), vr);
+
+ auto const & json_value = json_element["Value"];
+ for(auto const & json_item: json_value)
+ {
+ element.as_int().push_back(json_item.asInt64());
+ }
+ }
+ else if(vr == VR::SQ)
+ {
+ element = Element(Value::DataSets(), vr);
+ auto const & json_value = json_element["Value"];
+ for(auto const & json_item: json_value)
+ {
+ auto const dicom_item = as_dataset(json_item);
+ element.as_data_set().push_back(dicom_item);
+ }
+ }
+ else if(vr == VR::OB || vr == VR::OF || vr == VR::OW || vr == VR::UN)
+ {
+ element = Element(Value::Binary(), vr);
+
+ auto const & encoded = json_element["InlineBinary"].asString();
+ OFString const encoded_dcmtk(encoded.c_str());
+ unsigned char * decoded;
+ size_t const decoded_size =
+ OFStandard::decodeBase64(encoded_dcmtk, decoded);
+
+ element.as_binary().resize(decoded_size);
+ std::copy(decoded, decoded+decoded_size, element.as_binary().begin());
+
+ delete[] decoded;
+ }
+ else
+ {
+ throw Exception("Unknown VR: "+as_string(vr));
+ }
+
+ data_set.add(tag, element);
+ }
+
+ return data_set;
+}
+
+}
diff --git a/src/dcmtkpp/json_converter.h b/src/dcmtkpp/json_converter.h
new file mode 100644
index 0000000..b80c478
--- /dev/null
+++ b/src/dcmtkpp/json_converter.h
@@ -0,0 +1,26 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _6f5dc463_a89a_4f77_a0ed_36dca74b9e59
+#define _6f5dc463_a89a_4f77_a0ed_36dca74b9e59
+
+#include <jsoncpp/json/json.h>
+#include "dcmtkpp/DataSet.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Convert a data set to its JSON representation.
+Json::Value as_json(DataSet const & data_set);
+
+/// @brief Create a data set from its JSON representation.
+DataSet as_dataset(Json::Value const & json);
+
+}
+
+#endif // _6f5dc463_a89a_4f77_a0ed_36dca74b9e59
diff --git a/src/dcmtkpp/registry.h b/src/dcmtkpp/registry.h
new file mode 100644
index 0000000..279d7d8
--- /dev/null
+++ b/src/dcmtkpp/registry.h
@@ -0,0 +1,3867 @@
+/*************************************************************************
+* dcmtkpp - Copyright (C) Universite de Strasbourg
+* Distributed under the terms of the CeCILL-B license, as published by
+* the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+* http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+* for details.
+************************************************************************/
+
+#ifndef _afc7b2d7_0869_4fea_9a9b_7fe6228baca9
+#define _afc7b2d7_0869_4fea_9a9b_7fe6228baca9
+
+#include "dcmtkpp/Tag.h"
+
+namespace dcmtkpp
+{
+
+namespace registry
+{
+ Tag const CommandGroupLength(0x0000, 0x0000);
+ Tag const AffectedSOPClassUID(0x0000, 0x0002);
+ Tag const RequestedSOPClassUID(0x0000, 0x0003);
+ Tag const CommandField(0x0000, 0x0100);
+ Tag const MessageID(0x0000, 0x0110);
+ Tag const MessageIDBeingRespondedTo(0x0000, 0x0120);
+ Tag const MoveDestination(0x0000, 0x0600);
+ Tag const Priority(0x0000, 0x0700);
+ Tag const CommandDataSetType(0x0000, 0x0800);
+ Tag const Status(0x0000, 0x0900);
+ Tag const OffendingElement(0x0000, 0x0901);
+ Tag const ErrorComment(0x0000, 0x0902);
+ Tag const ErrorID(0x0000, 0x0903);
+ Tag const AffectedSOPInstanceUID(0x0000, 0x1000);
+ Tag const RequestedSOPInstanceUID(0x0000, 0x1001);
+ Tag const EventTypeID(0x0000, 0x1002);
+ Tag const AttributeIdentifierList(0x0000, 0x1005);
+ Tag const ActionTypeID(0x0000, 0x1008);
+ Tag const NumberOfRemainingSuboperations(0x0000, 0x1020);
+ Tag const NumberOfCompletedSuboperations(0x0000, 0x1021);
+ Tag const NumberOfFailedSuboperations(0x0000, 0x1022);
+ Tag const NumberOfWarningSuboperations(0x0000, 0x1023);
+ Tag const MoveOriginatorApplicationEntityTitle(0x0000, 0x1030);
+ Tag const MoveOriginatorMessageID(0x0000, 0x1031);
+ Tag const FileMetaInformationGroupLength(0x0002, 0x0000);
+ Tag const FileMetaInformationVersion(0x0002, 0x0001);
+ Tag const MediaStorageSOPClassUID(0x0002, 0x0002);
+ Tag const MediaStorageSOPInstanceUID(0x0002, 0x0003);
+ Tag const TransferSyntaxUID(0x0002, 0x0010);
+ Tag const ImplementationClassUID(0x0002, 0x0012);
+ Tag const ImplementationVersionName(0x0002, 0x0013);
+ Tag const SourceApplicationEntityTitle(0x0002, 0x0016);
+ Tag const SendingApplicationEntityTitle(0x0002, 0x0017);
+ Tag const ReceivingApplicationEntityTitle(0x0002, 0x0018);
+ Tag const PrivateInformationCreatorUID(0x0002, 0x0100);
+ Tag const PrivateInformation(0x0002, 0x0102);
+ Tag const FileSetID(0x0004, 0x1130);
+ Tag const FileSetDescriptorFileID(0x0004, 0x1141);
+ Tag const SpecificCharacterSetOfFileSetDescriptorFile(0x0004, 0x1142);
+ Tag const OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity(0x0004, 0x1200);
+ Tag const OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity(0x0004, 0x1202);
+ Tag const FileSetConsistencyFlag(0x0004, 0x1212);
+ Tag const DirectoryRecordSequence(0x0004, 0x1220);
+ Tag const OffsetOfTheNextDirectoryRecord(0x0004, 0x1400);
+ Tag const RecordInUseFlag(0x0004, 0x1410);
+ Tag const OffsetOfReferencedLowerLevelDirectoryEntity(0x0004, 0x1420);
+ Tag const DirectoryRecordType(0x0004, 0x1430);
+ Tag const PrivateRecordUID(0x0004, 0x1432);
+ Tag const ReferencedFileID(0x0004, 0x1500);
+ Tag const MRDRDirectoryRecordOffset(0x0004, 0x1504);
+ Tag const ReferencedSOPClassUIDInFile(0x0004, 0x1510);
+ Tag const ReferencedSOPInstanceUIDInFile(0x0004, 0x1511);
+ Tag const ReferencedTransferSyntaxUIDInFile(0x0004, 0x1512);
+ Tag const ReferencedRelatedGeneralSOPClassUIDInFile(0x0004, 0x151a);
+ Tag const NumberOfReferences(0x0004, 0x1600);
+ Tag const LengthToEnd(0x0008, 0x0001);
+ Tag const SpecificCharacterSet(0x0008, 0x0005);
+ Tag const LanguageCodeSequence(0x0008, 0x0006);
+ Tag const ImageType(0x0008, 0x0008);
+ Tag const RecognitionCode(0x0008, 0x0010);
+ Tag const InstanceCreationDate(0x0008, 0x0012);
+ Tag const InstanceCreationTime(0x0008, 0x0013);
+ Tag const InstanceCreatorUID(0x0008, 0x0014);
+ Tag const InstanceCoercionDateTime(0x0008, 0x0015);
+ Tag const SOPClassUID(0x0008, 0x0016);
+ Tag const SOPInstanceUID(0x0008, 0x0018);
+ Tag const RelatedGeneralSOPClassUID(0x0008, 0x001a);
+ Tag const OriginalSpecializedSOPClassUID(0x0008, 0x001b);
+ Tag const StudyDate(0x0008, 0x0020);
+ Tag const SeriesDate(0x0008, 0x0021);
+ Tag const AcquisitionDate(0x0008, 0x0022);
+ Tag const ContentDate(0x0008, 0x0023);
+ Tag const OverlayDate(0x0008, 0x0024);
+ Tag const CurveDate(0x0008, 0x0025);
+ Tag const AcquisitionDateTime(0x0008, 0x002a);
+ Tag const StudyTime(0x0008, 0x0030);
+ Tag const SeriesTime(0x0008, 0x0031);
+ Tag const AcquisitionTime(0x0008, 0x0032);
+ Tag const ContentTime(0x0008, 0x0033);
+ Tag const OverlayTime(0x0008, 0x0034);
+ Tag const CurveTime(0x0008, 0x0035);
+ Tag const DataSetType(0x0008, 0x0040);
+ Tag const DataSetSubtype(0x0008, 0x0041);
+ Tag const NuclearMedicineSeriesType(0x0008, 0x0042);
+ Tag const AccessionNumber(0x0008, 0x0050);
+ Tag const IssuerOfAccessionNumberSequence(0x0008, 0x0051);
+ Tag const QueryRetrieveLevel(0x0008, 0x0052);
+ Tag const QueryRetrieveView(0x0008, 0x0053);
+ Tag const RetrieveAETitle(0x0008, 0x0054);
+ Tag const InstanceAvailability(0x0008, 0x0056);
+ Tag const FailedSOPInstanceUIDList(0x0008, 0x0058);
+ Tag const Modality(0x0008, 0x0060);
+ Tag const ModalitiesInStudy(0x0008, 0x0061);
+ Tag const SOPClassesInStudy(0x0008, 0x0062);
+ Tag const ConversionType(0x0008, 0x0064);
+ Tag const PresentationIntentType(0x0008, 0x0068);
+ Tag const Manufacturer(0x0008, 0x0070);
+ Tag const InstitutionName(0x0008, 0x0080);
+ Tag const InstitutionAddress(0x0008, 0x0081);
+ Tag const InstitutionCodeSequence(0x0008, 0x0082);
+ Tag const ReferringPhysicianName(0x0008, 0x0090);
+ Tag const ReferringPhysicianAddress(0x0008, 0x0092);
+ Tag const ReferringPhysicianTelephoneNumbers(0x0008, 0x0094);
+ Tag const ReferringPhysicianIdentificationSequence(0x0008, 0x0096);
+ Tag const CodeValue(0x0008, 0x0100);
+ Tag const ExtendedCodeValue(0x0008, 0x0101);
+ Tag const CodingSchemeDesignator(0x0008, 0x0102);
+ Tag const CodingSchemeVersion(0x0008, 0x0103);
+ Tag const CodeMeaning(0x0008, 0x0104);
+ Tag const MappingResource(0x0008, 0x0105);
+ Tag const ContextGroupVersion(0x0008, 0x0106);
+ Tag const ContextGroupLocalVersion(0x0008, 0x0107);
+ Tag const ExtendedCodeMeaning(0x0008, 0x0108);
+ Tag const ContextGroupExtensionFlag(0x0008, 0x010b);
+ Tag const CodingSchemeUID(0x0008, 0x010c);
+ Tag const ContextGroupExtensionCreatorUID(0x0008, 0x010d);
+ Tag const ContextIdentifier(0x0008, 0x010f);
+ Tag const CodingSchemeIdentificationSequence(0x0008, 0x0110);
+ Tag const CodingSchemeRegistry(0x0008, 0x0112);
+ Tag const CodingSchemeExternalID(0x0008, 0x0114);
+ Tag const CodingSchemeName(0x0008, 0x0115);
+ Tag const CodingSchemeResponsibleOrganization(0x0008, 0x0116);
+ Tag const ContextUID(0x0008, 0x0117);
+ Tag const MappingResourceUID(0x0008, 0x0118);
+ Tag const LongCodeValue(0x0008, 0x0119);
+ Tag const URNCodeValue(0x0008, 0x0120);
+ Tag const EquivalentCodeSequence(0x0008, 0x0121);
+ Tag const TimezoneOffsetFromUTC(0x0008, 0x0201);
+ Tag const NetworkID(0x0008, 0x1000);
+ Tag const StationName(0x0008, 0x1010);
+ Tag const StudyDescription(0x0008, 0x1030);
+ Tag const ProcedureCodeSequence(0x0008, 0x1032);
+ Tag const SeriesDescription(0x0008, 0x103e);
+ Tag const SeriesDescriptionCodeSequence(0x0008, 0x103f);
+ Tag const InstitutionalDepartmentName(0x0008, 0x1040);
+ Tag const PhysiciansOfRecord(0x0008, 0x1048);
+ Tag const PhysiciansOfRecordIdentificationSequence(0x0008, 0x1049);
+ Tag const PerformingPhysicianName(0x0008, 0x1050);
+ Tag const PerformingPhysicianIdentificationSequence(0x0008, 0x1052);
+ Tag const NameOfPhysiciansReadingStudy(0x0008, 0x1060);
+ Tag const PhysiciansReadingStudyIdentificationSequence(0x0008, 0x1062);
+ Tag const OperatorsName(0x0008, 0x1070);
+ Tag const OperatorIdentificationSequence(0x0008, 0x1072);
+ Tag const AdmittingDiagnosesDescription(0x0008, 0x1080);
+ Tag const AdmittingDiagnosesCodeSequence(0x0008, 0x1084);
+ Tag const ManufacturerModelName(0x0008, 0x1090);
+ Tag const ReferencedResultsSequence(0x0008, 0x1100);
+ Tag const ReferencedStudySequence(0x0008, 0x1110);
+ Tag const ReferencedPerformedProcedureStepSequence(0x0008, 0x1111);
+ Tag const ReferencedSeriesSequence(0x0008, 0x1115);
+ Tag const ReferencedPatientSequence(0x0008, 0x1120);
+ Tag const ReferencedVisitSequence(0x0008, 0x1125);
+ Tag const ReferencedOverlaySequence(0x0008, 0x1130);
+ Tag const ReferencedStereometricInstanceSequence(0x0008, 0x1134);
+ Tag const ReferencedWaveformSequence(0x0008, 0x113a);
+ Tag const ReferencedImageSequence(0x0008, 0x1140);
+ Tag const ReferencedCurveSequence(0x0008, 0x1145);
+ Tag const ReferencedInstanceSequence(0x0008, 0x114a);
+ Tag const ReferencedRealWorldValueMappingInstanceSequence(0x0008, 0x114b);
+ Tag const ReferencedSOPClassUID(0x0008, 0x1150);
+ Tag const ReferencedSOPInstanceUID(0x0008, 0x1155);
+ Tag const SOPClassesSupported(0x0008, 0x115a);
+ Tag const ReferencedFrameNumber(0x0008, 0x1160);
+ Tag const SimpleFrameList(0x0008, 0x1161);
+ Tag const CalculatedFrameList(0x0008, 0x1162);
+ Tag const TimeRange(0x0008, 0x1163);
+ Tag const FrameExtractionSequence(0x0008, 0x1164);
+ Tag const MultiFrameSourceSOPInstanceUID(0x0008, 0x1167);
+ Tag const RetrieveURL(0x0008, 0x1190);
+ Tag const TransactionUID(0x0008, 0x1195);
+ Tag const WarningReason(0x0008, 0x1196);
+ Tag const FailureReason(0x0008, 0x1197);
+ Tag const FailedSOPSequence(0x0008, 0x1198);
+ Tag const ReferencedSOPSequence(0x0008, 0x1199);
+ Tag const StudiesContainingOtherReferencedInstancesSequence(0x0008, 0x1200);
+ Tag const RelatedSeriesSequence(0x0008, 0x1250);
+ Tag const LossyImageCompressionRetired(0x0008, 0x2110);
+ Tag const DerivationDescription(0x0008, 0x2111);
+ Tag const SourceImageSequence(0x0008, 0x2112);
+ Tag const StageName(0x0008, 0x2120);
+ Tag const StageNumber(0x0008, 0x2122);
+ Tag const NumberOfStages(0x0008, 0x2124);
+ Tag const ViewName(0x0008, 0x2127);
+ Tag const ViewNumber(0x0008, 0x2128);
+ Tag const NumberOfEventTimers(0x0008, 0x2129);
+ Tag const NumberOfViewsInStage(0x0008, 0x212a);
+ Tag const EventElapsedTimes(0x0008, 0x2130);
+ Tag const EventTimerNames(0x0008, 0x2132);
+ Tag const EventTimerSequence(0x0008, 0x2133);
+ Tag const EventTimeOffset(0x0008, 0x2134);
+ Tag const EventCodeSequence(0x0008, 0x2135);
+ Tag const StartTrim(0x0008, 0x2142);
+ Tag const StopTrim(0x0008, 0x2143);
+ Tag const RecommendedDisplayFrameRate(0x0008, 0x2144);
+ Tag const TransducerPosition(0x0008, 0x2200);
+ Tag const TransducerOrientation(0x0008, 0x2204);
+ Tag const AnatomicStructure(0x0008, 0x2208);
+ Tag const AnatomicRegionSequence(0x0008, 0x2218);
+ Tag const AnatomicRegionModifierSequence(0x0008, 0x2220);
+ Tag const PrimaryAnatomicStructureSequence(0x0008, 0x2228);
+ Tag const AnatomicStructureSpaceOrRegionSequence(0x0008, 0x2229);
+ Tag const PrimaryAnatomicStructureModifierSequence(0x0008, 0x2230);
+ Tag const TransducerPositionSequence(0x0008, 0x2240);
+ Tag const TransducerPositionModifierSequence(0x0008, 0x2242);
+ Tag const TransducerOrientationSequence(0x0008, 0x2244);
+ Tag const TransducerOrientationModifierSequence(0x0008, 0x2246);
+ Tag const AnatomicStructureSpaceOrRegionCodeSequenceTrial(0x0008, 0x2251);
+ Tag const AnatomicPortalOfEntranceCodeSequenceTrial(0x0008, 0x2253);
+ Tag const AnatomicApproachDirectionCodeSequenceTrial(0x0008, 0x2255);
+ Tag const AnatomicPerspectiveDescriptionTrial(0x0008, 0x2256);
+ Tag const AnatomicPerspectiveCodeSequenceTrial(0x0008, 0x2257);
+ Tag const AnatomicLocationOfExaminingInstrumentDescriptionTrial(0x0008, 0x2258);
+ Tag const AnatomicLocationOfExaminingInstrumentCodeSequenceTrial(0x0008, 0x2259);
+ Tag const AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial(0x0008, 0x225a);
+ Tag const OnAxisBackgroundAnatomicStructureCodeSequenceTrial(0x0008, 0x225c);
+ Tag const AlternateRepresentationSequence(0x0008, 0x3001);
+ Tag const IrradiationEventUID(0x0008, 0x3010);
+ Tag const SourceIrradiationEventSequence(0x0008, 0x3011);
+ Tag const RadiopharmaceuticalAdministrationEventUID(0x0008, 0x3012);
+ Tag const IdentifyingComments(0x0008, 0x4000);
+ Tag const FrameType(0x0008, 0x9007);
+ Tag const ReferencedImageEvidenceSequence(0x0008, 0x9092);
+ Tag const ReferencedRawDataSequence(0x0008, 0x9121);
+ Tag const CreatorVersionUID(0x0008, 0x9123);
+ Tag const DerivationImageSequence(0x0008, 0x9124);
+ Tag const SourceImageEvidenceSequence(0x0008, 0x9154);
+ Tag const PixelPresentation(0x0008, 0x9205);
+ Tag const VolumetricProperties(0x0008, 0x9206);
+ Tag const VolumeBasedCalculationTechnique(0x0008, 0x9207);
+ Tag const ComplexImageComponent(0x0008, 0x9208);
+ Tag const AcquisitionContrast(0x0008, 0x9209);
+ Tag const DerivationCodeSequence(0x0008, 0x9215);
+ Tag const ReferencedPresentationStateSequence(0x0008, 0x9237);
+ Tag const ReferencedOtherPlaneSequence(0x0008, 0x9410);
+ Tag const FrameDisplaySequence(0x0008, 0x9458);
+ Tag const RecommendedDisplayFrameRateInFloat(0x0008, 0x9459);
+ Tag const SkipFrameRangeFlag(0x0008, 0x9460);
+ Tag const PatientName(0x0010, 0x0010);
+ Tag const PatientID(0x0010, 0x0020);
+ Tag const IssuerOfPatientID(0x0010, 0x0021);
+ Tag const TypeOfPatientID(0x0010, 0x0022);
+ Tag const IssuerOfPatientIDQualifiersSequence(0x0010, 0x0024);
+ Tag const PatientBirthDate(0x0010, 0x0030);
+ Tag const PatientBirthTime(0x0010, 0x0032);
+ Tag const PatientSex(0x0010, 0x0040);
+ Tag const PatientInsurancePlanCodeSequence(0x0010, 0x0050);
+ Tag const PatientPrimaryLanguageCodeSequence(0x0010, 0x0101);
+ Tag const PatientPrimaryLanguageModifierCodeSequence(0x0010, 0x0102);
+ Tag const QualityControlSubject(0x0010, 0x0200);
+ Tag const QualityControlSubjectTypeCodeSequence(0x0010, 0x0201);
+ Tag const OtherPatientIDs(0x0010, 0x1000);
+ Tag const OtherPatientNames(0x0010, 0x1001);
+ Tag const OtherPatientIDsSequence(0x0010, 0x1002);
+ Tag const PatientBirthName(0x0010, 0x1005);
+ Tag const PatientAge(0x0010, 0x1010);
+ Tag const PatientSize(0x0010, 0x1020);
+ Tag const PatientSizeCodeSequence(0x0010, 0x1021);
+ Tag const PatientWeight(0x0010, 0x1030);
+ Tag const PatientAddress(0x0010, 0x1040);
+ Tag const InsurancePlanIdentification(0x0010, 0x1050);
+ Tag const PatientMotherBirthName(0x0010, 0x1060);
+ Tag const MilitaryRank(0x0010, 0x1080);
+ Tag const BranchOfService(0x0010, 0x1081);
+ Tag const MedicalRecordLocator(0x0010, 0x1090);
+ Tag const ReferencedPatientPhotoSequence(0x0010, 0x1100);
+ Tag const MedicalAlerts(0x0010, 0x2000);
+ Tag const Allergies(0x0010, 0x2110);
+ Tag const CountryOfResidence(0x0010, 0x2150);
+ Tag const RegionOfResidence(0x0010, 0x2152);
+ Tag const PatientTelephoneNumbers(0x0010, 0x2154);
+ Tag const EthnicGroup(0x0010, 0x2160);
+ Tag const Occupation(0x0010, 0x2180);
+ Tag const SmokingStatus(0x0010, 0x21a0);
+ Tag const AdditionalPatientHistory(0x0010, 0x21b0);
+ Tag const PregnancyStatus(0x0010, 0x21c0);
+ Tag const LastMenstrualDate(0x0010, 0x21d0);
+ Tag const PatientReligiousPreference(0x0010, 0x21f0);
+ Tag const PatientSpeciesDescription(0x0010, 0x2201);
+ Tag const PatientSpeciesCodeSequence(0x0010, 0x2202);
+ Tag const PatientSexNeutered(0x0010, 0x2203);
+ Tag const AnatomicalOrientationType(0x0010, 0x2210);
+ Tag const PatientBreedDescription(0x0010, 0x2292);
+ Tag const PatientBreedCodeSequence(0x0010, 0x2293);
+ Tag const BreedRegistrationSequence(0x0010, 0x2294);
+ Tag const BreedRegistrationNumber(0x0010, 0x2295);
+ Tag const BreedRegistryCodeSequence(0x0010, 0x2296);
+ Tag const ResponsiblePerson(0x0010, 0x2297);
+ Tag const ResponsiblePersonRole(0x0010, 0x2298);
+ Tag const ResponsibleOrganization(0x0010, 0x2299);
+ Tag const PatientComments(0x0010, 0x4000);
+ Tag const ExaminedBodyThickness(0x0010, 0x9431);
+ Tag const ClinicalTrialSponsorName(0x0012, 0x0010);
+ Tag const ClinicalTrialProtocolID(0x0012, 0x0020);
+ Tag const ClinicalTrialProtocolName(0x0012, 0x0021);
+ Tag const ClinicalTrialSiteID(0x0012, 0x0030);
+ Tag const ClinicalTrialSiteName(0x0012, 0x0031);
+ Tag const ClinicalTrialSubjectID(0x0012, 0x0040);
+ Tag const ClinicalTrialSubjectReadingID(0x0012, 0x0042);
+ Tag const ClinicalTrialTimePointID(0x0012, 0x0050);
+ Tag const ClinicalTrialTimePointDescription(0x0012, 0x0051);
+ Tag const ClinicalTrialCoordinatingCenterName(0x0012, 0x0060);
+ Tag const PatientIdentityRemoved(0x0012, 0x0062);
+ Tag const DeidentificationMethod(0x0012, 0x0063);
+ Tag const DeidentificationMethodCodeSequence(0x0012, 0x0064);
+ Tag const ClinicalTrialSeriesID(0x0012, 0x0071);
+ Tag const ClinicalTrialSeriesDescription(0x0012, 0x0072);
+ Tag const ClinicalTrialProtocolEthicsCommitteeName(0x0012, 0x0081);
+ Tag const ClinicalTrialProtocolEthicsCommitteeApprovalNumber(0x0012, 0x0082);
+ Tag const ConsentForClinicalTrialUseSequence(0x0012, 0x0083);
+ Tag const DistributionType(0x0012, 0x0084);
+ Tag const ConsentForDistributionFlag(0x0012, 0x0085);
+ Tag const CADFileFormat(0x0014, 0x0023);
+ Tag const ComponentReferenceSystem(0x0014, 0x0024);
+ Tag const ComponentManufacturingProcedure(0x0014, 0x0025);
+ Tag const ComponentManufacturer(0x0014, 0x0028);
+ Tag const MaterialThickness(0x0014, 0x0030);
+ Tag const MaterialPipeDiameter(0x0014, 0x0032);
+ Tag const MaterialIsolationDiameter(0x0014, 0x0034);
+ Tag const MaterialGrade(0x0014, 0x0042);
+ Tag const MaterialPropertiesDescription(0x0014, 0x0044);
+ Tag const MaterialPropertiesFileFormatRetired(0x0014, 0x0045);
+ Tag const MaterialNotes(0x0014, 0x0046);
+ Tag const ComponentShape(0x0014, 0x0050);
+ Tag const CurvatureType(0x0014, 0x0052);
+ Tag const OuterDiameter(0x0014, 0x0054);
+ Tag const InnerDiameter(0x0014, 0x0056);
+ Tag const ActualEnvironmentalConditions(0x0014, 0x1010);
+ Tag const ExpiryDate(0x0014, 0x1020);
+ Tag const EnvironmentalConditions(0x0014, 0x1040);
+ Tag const EvaluatorSequence(0x0014, 0x2002);
+ Tag const EvaluatorNumber(0x0014, 0x2004);
+ Tag const EvaluatorName(0x0014, 0x2006);
+ Tag const EvaluationAttempt(0x0014, 0x2008);
+ Tag const IndicationSequence(0x0014, 0x2012);
+ Tag const IndicationNumber(0x0014, 0x2014);
+ Tag const IndicationLabel(0x0014, 0x2016);
+ Tag const IndicationDescription(0x0014, 0x2018);
+ Tag const IndicationType(0x0014, 0x201a);
+ Tag const IndicationDisposition(0x0014, 0x201c);
+ Tag const IndicationROISequence(0x0014, 0x201e);
+ Tag const IndicationPhysicalPropertySequence(0x0014, 0x2030);
+ Tag const PropertyLabel(0x0014, 0x2032);
+ Tag const CoordinateSystemNumberOfAxes(0x0014, 0x2202);
+ Tag const CoordinateSystemAxesSequence(0x0014, 0x2204);
+ Tag const CoordinateSystemAxisDescription(0x0014, 0x2206);
+ Tag const CoordinateSystemDataSetMapping(0x0014, 0x2208);
+ Tag const CoordinateSystemAxisNumber(0x0014, 0x220a);
+ Tag const CoordinateSystemAxisType(0x0014, 0x220c);
+ Tag const CoordinateSystemAxisUnits(0x0014, 0x220e);
+ Tag const CoordinateSystemAxisValues(0x0014, 0x2210);
+ Tag const CoordinateSystemTransformSequence(0x0014, 0x2220);
+ Tag const TransformDescription(0x0014, 0x2222);
+ Tag const TransformNumberOfAxes(0x0014, 0x2224);
+ Tag const TransformOrderOfAxes(0x0014, 0x2226);
+ Tag const TransformedAxisUnits(0x0014, 0x2228);
+ Tag const CoordinateSystemTransformRotationAndScaleMatrix(0x0014, 0x222a);
+ Tag const CoordinateSystemTransformTranslationMatrix(0x0014, 0x222c);
+ Tag const InternalDetectorFrameTime(0x0014, 0x3011);
+ Tag const NumberOfFramesIntegrated(0x0014, 0x3012);
+ Tag const DetectorTemperatureSequence(0x0014, 0x3020);
+ Tag const SensorName(0x0014, 0x3022);
+ Tag const HorizontalOffsetOfSensor(0x0014, 0x3024);
+ Tag const VerticalOffsetOfSensor(0x0014, 0x3026);
+ Tag const SensorTemperature(0x0014, 0x3028);
+ Tag const DarkCurrentSequence(0x0014, 0x3040);
+ Tag const DarkCurrentCounts(0x0014, 0x3050);
+ Tag const GainCorrectionReferenceSequence(0x0014, 0x3060);
+ Tag const AirCounts(0x0014, 0x3070);
+ Tag const KVUsedInGainCalibration(0x0014, 0x3071);
+ Tag const MAUsedInGainCalibration(0x0014, 0x3072);
+ Tag const NumberOfFramesUsedForIntegration(0x0014, 0x3073);
+ Tag const FilterMaterialUsedInGainCalibration(0x0014, 0x3074);
+ Tag const FilterThicknessUsedInGainCalibration(0x0014, 0x3075);
+ Tag const DateOfGainCalibration(0x0014, 0x3076);
+ Tag const TimeOfGainCalibration(0x0014, 0x3077);
+ Tag const BadPixelImage(0x0014, 0x3080);
+ Tag const CalibrationNotes(0x0014, 0x3099);
+ Tag const PulserEquipmentSequence(0x0014, 0x4002);
+ Tag const PulserType(0x0014, 0x4004);
+ Tag const PulserNotes(0x0014, 0x4006);
+ Tag const ReceiverEquipmentSequence(0x0014, 0x4008);
+ Tag const AmplifierType(0x0014, 0x400a);
+ Tag const ReceiverNotes(0x0014, 0x400c);
+ Tag const PreAmplifierEquipmentSequence(0x0014, 0x400e);
+ Tag const PreAmplifierNotes(0x0014, 0x400f);
+ Tag const TransmitTransducerSequence(0x0014, 0x4010);
+ Tag const ReceiveTransducerSequence(0x0014, 0x4011);
+ Tag const NumberOfElements(0x0014, 0x4012);
+ Tag const ElementShape(0x0014, 0x4013);
+ Tag const ElementDimensionA(0x0014, 0x4014);
+ Tag const ElementDimensionB(0x0014, 0x4015);
+ Tag const ElementPitchA(0x0014, 0x4016);
+ Tag const MeasuredBeamDimensionA(0x0014, 0x4017);
+ Tag const MeasuredBeamDimensionB(0x0014, 0x4018);
+ Tag const LocationOfMeasuredBeamDiameter(0x0014, 0x4019);
+ Tag const NominalFrequency(0x0014, 0x401a);
+ Tag const MeasuredCenterFrequency(0x0014, 0x401b);
+ Tag const MeasuredBandwidth(0x0014, 0x401c);
+ Tag const ElementPitchB(0x0014, 0x401d);
+ Tag const PulserSettingsSequence(0x0014, 0x4020);
+ Tag const PulseWidth(0x0014, 0x4022);
+ Tag const ExcitationFrequency(0x0014, 0x4024);
+ Tag const ModulationType(0x0014, 0x4026);
+ Tag const Damping(0x0014, 0x4028);
+ Tag const ReceiverSettingsSequence(0x0014, 0x4030);
+ Tag const AcquiredSoundpathLength(0x0014, 0x4031);
+ Tag const AcquisitionCompressionType(0x0014, 0x4032);
+ Tag const AcquisitionSampleSize(0x0014, 0x4033);
+ Tag const RectifierSmoothing(0x0014, 0x4034);
+ Tag const DACSequence(0x0014, 0x4035);
+ Tag const DACType(0x0014, 0x4036);
+ Tag const DACGainPoints(0x0014, 0x4038);
+ Tag const DACTimePoints(0x0014, 0x403a);
+ Tag const DACAmplitude(0x0014, 0x403c);
+ Tag const PreAmplifierSettingsSequence(0x0014, 0x4040);
+ Tag const TransmitTransducerSettingsSequence(0x0014, 0x4050);
+ Tag const ReceiveTransducerSettingsSequence(0x0014, 0x4051);
+ Tag const IncidentAngle(0x0014, 0x4052);
+ Tag const CouplingTechnique(0x0014, 0x4054);
+ Tag const CouplingMedium(0x0014, 0x4056);
+ Tag const CouplingVelocity(0x0014, 0x4057);
+ Tag const ProbeCenterLocationX(0x0014, 0x4058);
+ Tag const ProbeCenterLocationZ(0x0014, 0x4059);
+ Tag const SoundPathLength(0x0014, 0x405a);
+ Tag const DelayLawIdentifier(0x0014, 0x405c);
+ Tag const GateSettingsSequence(0x0014, 0x4060);
+ Tag const GateThreshold(0x0014, 0x4062);
+ Tag const VelocityOfSound(0x0014, 0x4064);
+ Tag const CalibrationSettingsSequence(0x0014, 0x4070);
+ Tag const CalibrationProcedure(0x0014, 0x4072);
+ Tag const ProcedureVersion(0x0014, 0x4074);
+ Tag const ProcedureCreationDate(0x0014, 0x4076);
+ Tag const ProcedureExpirationDate(0x0014, 0x4078);
+ Tag const ProcedureLastModifiedDate(0x0014, 0x407a);
+ Tag const CalibrationTime(0x0014, 0x407c);
+ Tag const CalibrationDate(0x0014, 0x407e);
+ Tag const ProbeDriveEquipmentSequence(0x0014, 0x4080);
+ Tag const DriveType(0x0014, 0x4081);
+ Tag const ProbeDriveNotes(0x0014, 0x4082);
+ Tag const DriveProbeSequence(0x0014, 0x4083);
+ Tag const ProbeInductance(0x0014, 0x4084);
+ Tag const ProbeResistance(0x0014, 0x4085);
+ Tag const ReceiveProbeSequence(0x0014, 0x4086);
+ Tag const ProbeDriveSettingsSequence(0x0014, 0x4087);
+ Tag const BridgeResistors(0x0014, 0x4088);
+ Tag const ProbeOrientationAngle(0x0014, 0x4089);
+ Tag const UserSelectedGainY(0x0014, 0x408b);
+ Tag const UserSelectedPhase(0x0014, 0x408c);
+ Tag const UserSelectedOffsetX(0x0014, 0x408d);
+ Tag const UserSelectedOffsetY(0x0014, 0x408e);
+ Tag const ChannelSettingsSequence(0x0014, 0x4091);
+ Tag const ChannelThreshold(0x0014, 0x4092);
+ Tag const ScannerSettingsSequence(0x0014, 0x409a);
+ Tag const ScanProcedure(0x0014, 0x409b);
+ Tag const TranslationRateX(0x0014, 0x409c);
+ Tag const TranslationRateY(0x0014, 0x409d);
+ Tag const ChannelOverlap(0x0014, 0x409f);
+ Tag const ImageQualityIndicatorType(0x0014, 0x40a0);
+ Tag const ImageQualityIndicatorMaterial(0x0014, 0x40a1);
+ Tag const ImageQualityIndicatorSize(0x0014, 0x40a2);
+ Tag const LINACEnergy(0x0014, 0x5002);
+ Tag const LINACOutput(0x0014, 0x5004);
+ Tag const ActiveAperture(0x0014, 0x5100);
+ Tag const TotalAperture(0x0014, 0x5101);
+ Tag const ApertureElevation(0x0014, 0x5102);
+ Tag const MainLobeAngle(0x0014, 0x5103);
+ Tag const MainRoofAngle(0x0014, 0x5104);
+ Tag const ConnectorType(0x0014, 0x5105);
+ Tag const WedgeModelNumber(0x0014, 0x5106);
+ Tag const WedgeAngleFloat(0x0014, 0x5107);
+ Tag const WedgeRoofAngle(0x0014, 0x5108);
+ Tag const WedgeElement1Position(0x0014, 0x5109);
+ Tag const WedgeMaterialVelocity(0x0014, 0x510a);
+ Tag const WedgeMaterial(0x0014, 0x510b);
+ Tag const WedgeOffsetZ(0x0014, 0x510c);
+ Tag const WedgeOriginOffsetX(0x0014, 0x510d);
+ Tag const WedgeTimeDelay(0x0014, 0x510e);
+ Tag const WedgeName(0x0014, 0x510f);
+ Tag const WedgeManufacturerName(0x0014, 0x5110);
+ Tag const WedgeDescription(0x0014, 0x5111);
+ Tag const NominalBeamAngle(0x0014, 0x5112);
+ Tag const WedgeOffsetX(0x0014, 0x5113);
+ Tag const WedgeOffsetY(0x0014, 0x5114);
+ Tag const WedgeTotalLength(0x0014, 0x5115);
+ Tag const WedgeInContactLength(0x0014, 0x5116);
+ Tag const WedgeFrontGap(0x0014, 0x5117);
+ Tag const WedgeTotalHeight(0x0014, 0x5118);
+ Tag const WedgeFrontHeight(0x0014, 0x5119);
+ Tag const WedgeRearHeight(0x0014, 0x511a);
+ Tag const WedgeTotalWidth(0x0014, 0x511b);
+ Tag const WedgeInContactWidth(0x0014, 0x511c);
+ Tag const WedgeChamferHeight(0x0014, 0x511d);
+ Tag const WedgeCurve(0x0014, 0x511e);
+ Tag const RadiusAlongWedge(0x0014, 0x511f);
+ Tag const ContrastBolusAgent(0x0018, 0x0010);
+ Tag const ContrastBolusAgentSequence(0x0018, 0x0012);
+ Tag const ContrastBolusT1Relaxivity(0x0018, 0x0013);
+ Tag const ContrastBolusAdministrationRouteSequence(0x0018, 0x0014);
+ Tag const BodyPartExamined(0x0018, 0x0015);
+ Tag const ScanningSequence(0x0018, 0x0020);
+ Tag const SequenceVariant(0x0018, 0x0021);
+ Tag const ScanOptions(0x0018, 0x0022);
+ Tag const MRAcquisitionType(0x0018, 0x0023);
+ Tag const SequenceName(0x0018, 0x0024);
+ Tag const AngioFlag(0x0018, 0x0025);
+ Tag const InterventionDrugInformationSequence(0x0018, 0x0026);
+ Tag const InterventionDrugStopTime(0x0018, 0x0027);
+ Tag const InterventionDrugDose(0x0018, 0x0028);
+ Tag const InterventionDrugCodeSequence(0x0018, 0x0029);
+ Tag const AdditionalDrugSequence(0x0018, 0x002a);
+ Tag const Radionuclide(0x0018, 0x0030);
+ Tag const Radiopharmaceutical(0x0018, 0x0031);
+ Tag const EnergyWindowCenterline(0x0018, 0x0032);
+ Tag const EnergyWindowTotalWidth(0x0018, 0x0033);
+ Tag const InterventionDrugName(0x0018, 0x0034);
+ Tag const InterventionDrugStartTime(0x0018, 0x0035);
+ Tag const InterventionSequence(0x0018, 0x0036);
+ Tag const TherapyType(0x0018, 0x0037);
+ Tag const InterventionStatus(0x0018, 0x0038);
+ Tag const TherapyDescription(0x0018, 0x0039);
+ Tag const InterventionDescription(0x0018, 0x003a);
+ Tag const CineRate(0x0018, 0x0040);
+ Tag const InitialCineRunState(0x0018, 0x0042);
+ Tag const SliceThickness(0x0018, 0x0050);
+ Tag const KVP(0x0018, 0x0060);
+ Tag const CountsAccumulated(0x0018, 0x0070);
+ Tag const AcquisitionTerminationCondition(0x0018, 0x0071);
+ Tag const EffectiveDuration(0x0018, 0x0072);
+ Tag const AcquisitionStartCondition(0x0018, 0x0073);
+ Tag const AcquisitionStartConditionData(0x0018, 0x0074);
+ Tag const AcquisitionTerminationConditionData(0x0018, 0x0075);
+ Tag const RepetitionTime(0x0018, 0x0080);
+ Tag const EchoTime(0x0018, 0x0081);
+ Tag const InversionTime(0x0018, 0x0082);
+ Tag const NumberOfAverages(0x0018, 0x0083);
+ Tag const ImagingFrequency(0x0018, 0x0084);
+ Tag const ImagedNucleus(0x0018, 0x0085);
+ Tag const EchoNumbers(0x0018, 0x0086);
+ Tag const MagneticFieldStrength(0x0018, 0x0087);
+ Tag const SpacingBetweenSlices(0x0018, 0x0088);
+ Tag const NumberOfPhaseEncodingSteps(0x0018, 0x0089);
+ Tag const DataCollectionDiameter(0x0018, 0x0090);
+ Tag const EchoTrainLength(0x0018, 0x0091);
+ Tag const PercentSampling(0x0018, 0x0093);
+ Tag const PercentPhaseFieldOfView(0x0018, 0x0094);
+ Tag const PixelBandwidth(0x0018, 0x0095);
+ Tag const DeviceSerialNumber(0x0018, 0x1000);
+ Tag const DeviceUID(0x0018, 0x1002);
+ Tag const DeviceID(0x0018, 0x1003);
+ Tag const PlateID(0x0018, 0x1004);
+ Tag const GeneratorID(0x0018, 0x1005);
+ Tag const GridID(0x0018, 0x1006);
+ Tag const CassetteID(0x0018, 0x1007);
+ Tag const GantryID(0x0018, 0x1008);
+ Tag const SecondaryCaptureDeviceID(0x0018, 0x1010);
+ Tag const HardcopyCreationDeviceID(0x0018, 0x1011);
+ Tag const DateOfSecondaryCapture(0x0018, 0x1012);
+ Tag const TimeOfSecondaryCapture(0x0018, 0x1014);
+ Tag const SecondaryCaptureDeviceManufacturer(0x0018, 0x1016);
+ Tag const HardcopyDeviceManufacturer(0x0018, 0x1017);
+ Tag const SecondaryCaptureDeviceManufacturerModelName(0x0018, 0x1018);
+ Tag const SecondaryCaptureDeviceSoftwareVersions(0x0018, 0x1019);
+ Tag const HardcopyDeviceSoftwareVersion(0x0018, 0x101a);
+ Tag const HardcopyDeviceManufacturerModelName(0x0018, 0x101b);
+ Tag const SoftwareVersions(0x0018, 0x1020);
+ Tag const VideoImageFormatAcquired(0x0018, 0x1022);
+ Tag const DigitalImageFormatAcquired(0x0018, 0x1023);
+ Tag const ProtocolName(0x0018, 0x1030);
+ Tag const ContrastBolusRoute(0x0018, 0x1040);
+ Tag const ContrastBolusVolume(0x0018, 0x1041);
+ Tag const ContrastBolusStartTime(0x0018, 0x1042);
+ Tag const ContrastBolusStopTime(0x0018, 0x1043);
+ Tag const ContrastBolusTotalDose(0x0018, 0x1044);
+ Tag const SyringeCounts(0x0018, 0x1045);
+ Tag const ContrastFlowRate(0x0018, 0x1046);
+ Tag const ContrastFlowDuration(0x0018, 0x1047);
+ Tag const ContrastBolusIngredient(0x0018, 0x1048);
+ Tag const ContrastBolusIngredientConcentration(0x0018, 0x1049);
+ Tag const SpatialResolution(0x0018, 0x1050);
+ Tag const TriggerTime(0x0018, 0x1060);
+ Tag const TriggerSourceOrType(0x0018, 0x1061);
+ Tag const NominalInterval(0x0018, 0x1062);
+ Tag const FrameTime(0x0018, 0x1063);
+ Tag const CardiacFramingType(0x0018, 0x1064);
+ Tag const FrameTimeVector(0x0018, 0x1065);
+ Tag const FrameDelay(0x0018, 0x1066);
+ Tag const ImageTriggerDelay(0x0018, 0x1067);
+ Tag const MultiplexGroupTimeOffset(0x0018, 0x1068);
+ Tag const TriggerTimeOffset(0x0018, 0x1069);
+ Tag const SynchronizationTrigger(0x0018, 0x106a);
+ Tag const SynchronizationChannel(0x0018, 0x106c);
+ Tag const TriggerSamplePosition(0x0018, 0x106e);
+ Tag const RadiopharmaceuticalRoute(0x0018, 0x1070);
+ Tag const RadiopharmaceuticalVolume(0x0018, 0x1071);
+ Tag const RadiopharmaceuticalStartTime(0x0018, 0x1072);
+ Tag const RadiopharmaceuticalStopTime(0x0018, 0x1073);
+ Tag const RadionuclideTotalDose(0x0018, 0x1074);
+ Tag const RadionuclideHalfLife(0x0018, 0x1075);
+ Tag const RadionuclidePositronFraction(0x0018, 0x1076);
+ Tag const RadiopharmaceuticalSpecificActivity(0x0018, 0x1077);
+ Tag const RadiopharmaceuticalStartDateTime(0x0018, 0x1078);
+ Tag const RadiopharmaceuticalStopDateTime(0x0018, 0x1079);
+ Tag const BeatRejectionFlag(0x0018, 0x1080);
+ Tag const LowRRValue(0x0018, 0x1081);
+ Tag const HighRRValue(0x0018, 0x1082);
+ Tag const IntervalsAcquired(0x0018, 0x1083);
+ Tag const IntervalsRejected(0x0018, 0x1084);
+ Tag const PVCRejection(0x0018, 0x1085);
+ Tag const SkipBeats(0x0018, 0x1086);
+ Tag const HeartRate(0x0018, 0x1088);
+ Tag const CardiacNumberOfImages(0x0018, 0x1090);
+ Tag const TriggerWindow(0x0018, 0x1094);
+ Tag const ReconstructionDiameter(0x0018, 0x1100);
+ Tag const DistanceSourceToDetector(0x0018, 0x1110);
+ Tag const DistanceSourceToPatient(0x0018, 0x1111);
+ Tag const EstimatedRadiographicMagnificationFactor(0x0018, 0x1114);
+ Tag const GantryDetectorTilt(0x0018, 0x1120);
+ Tag const GantryDetectorSlew(0x0018, 0x1121);
+ Tag const TableHeight(0x0018, 0x1130);
+ Tag const TableTraverse(0x0018, 0x1131);
+ Tag const TableMotion(0x0018, 0x1134);
+ Tag const TableVerticalIncrement(0x0018, 0x1135);
+ Tag const TableLateralIncrement(0x0018, 0x1136);
+ Tag const TableLongitudinalIncrement(0x0018, 0x1137);
+ Tag const TableAngle(0x0018, 0x1138);
+ Tag const TableType(0x0018, 0x113a);
+ Tag const RotationDirection(0x0018, 0x1140);
+ Tag const AngularPosition(0x0018, 0x1141);
+ Tag const RadialPosition(0x0018, 0x1142);
+ Tag const ScanArc(0x0018, 0x1143);
+ Tag const AngularStep(0x0018, 0x1144);
+ Tag const CenterOfRotationOffset(0x0018, 0x1145);
+ Tag const RotationOffset(0x0018, 0x1146);
+ Tag const FieldOfViewShape(0x0018, 0x1147);
+ Tag const FieldOfViewDimensions(0x0018, 0x1149);
+ Tag const ExposureTime(0x0018, 0x1150);
+ Tag const XRayTubeCurrent(0x0018, 0x1151);
+ Tag const Exposure(0x0018, 0x1152);
+ Tag const ExposureInuAs(0x0018, 0x1153);
+ Tag const AveragePulseWidth(0x0018, 0x1154);
+ Tag const RadiationSetting(0x0018, 0x1155);
+ Tag const RectificationType(0x0018, 0x1156);
+ Tag const RadiationMode(0x0018, 0x115a);
+ Tag const ImageAndFluoroscopyAreaDoseProduct(0x0018, 0x115e);
+ Tag const FilterType(0x0018, 0x1160);
+ Tag const TypeOfFilters(0x0018, 0x1161);
+ Tag const IntensifierSize(0x0018, 0x1162);
+ Tag const ImagerPixelSpacing(0x0018, 0x1164);
+ Tag const Grid(0x0018, 0x1166);
+ Tag const GeneratorPower(0x0018, 0x1170);
+ Tag const CollimatorGridName(0x0018, 0x1180);
+ Tag const CollimatorType(0x0018, 0x1181);
+ Tag const FocalDistance(0x0018, 0x1182);
+ Tag const XFocusCenter(0x0018, 0x1183);
+ Tag const YFocusCenter(0x0018, 0x1184);
+ Tag const FocalSpots(0x0018, 0x1190);
+ Tag const AnodeTargetMaterial(0x0018, 0x1191);
+ Tag const BodyPartThickness(0x0018, 0x11a0);
+ Tag const CompressionForce(0x0018, 0x11a2);
+ Tag const PaddleDescription(0x0018, 0x11a4);
+ Tag const DateOfLastCalibration(0x0018, 0x1200);
+ Tag const TimeOfLastCalibration(0x0018, 0x1201);
+ Tag const DateTimeOfLastCalibration(0x0018, 0x1202);
+ Tag const ConvolutionKernel(0x0018, 0x1210);
+ Tag const UpperLowerPixelValues(0x0018, 0x1240);
+ Tag const ActualFrameDuration(0x0018, 0x1242);
+ Tag const CountRate(0x0018, 0x1243);
+ Tag const PreferredPlaybackSequencing(0x0018, 0x1244);
+ Tag const ReceiveCoilName(0x0018, 0x1250);
+ Tag const TransmitCoilName(0x0018, 0x1251);
+ Tag const PlateType(0x0018, 0x1260);
+ Tag const PhosphorType(0x0018, 0x1261);
+ Tag const ScanVelocity(0x0018, 0x1300);
+ Tag const WholeBodyTechnique(0x0018, 0x1301);
+ Tag const ScanLength(0x0018, 0x1302);
+ Tag const AcquisitionMatrix(0x0018, 0x1310);
+ Tag const InPlanePhaseEncodingDirection(0x0018, 0x1312);
+ Tag const FlipAngle(0x0018, 0x1314);
+ Tag const VariableFlipAngleFlag(0x0018, 0x1315);
+ Tag const SAR(0x0018, 0x1316);
+ Tag const dBdt(0x0018, 0x1318);
+ Tag const AcquisitionDeviceProcessingDescription(0x0018, 0x1400);
+ Tag const AcquisitionDeviceProcessingCode(0x0018, 0x1401);
+ Tag const CassetteOrientation(0x0018, 0x1402);
+ Tag const CassetteSize(0x0018, 0x1403);
+ Tag const ExposuresOnPlate(0x0018, 0x1404);
+ Tag const RelativeXRayExposure(0x0018, 0x1405);
+ Tag const ExposureIndex(0x0018, 0x1411);
+ Tag const TargetExposureIndex(0x0018, 0x1412);
+ Tag const DeviationIndex(0x0018, 0x1413);
+ Tag const ColumnAngulation(0x0018, 0x1450);
+ Tag const TomoLayerHeight(0x0018, 0x1460);
+ Tag const TomoAngle(0x0018, 0x1470);
+ Tag const TomoTime(0x0018, 0x1480);
+ Tag const TomoType(0x0018, 0x1490);
+ Tag const TomoClass(0x0018, 0x1491);
+ Tag const NumberOfTomosynthesisSourceImages(0x0018, 0x1495);
+ Tag const PositionerMotion(0x0018, 0x1500);
+ Tag const PositionerType(0x0018, 0x1508);
+ Tag const PositionerPrimaryAngle(0x0018, 0x1510);
+ Tag const PositionerSecondaryAngle(0x0018, 0x1511);
+ Tag const PositionerPrimaryAngleIncrement(0x0018, 0x1520);
+ Tag const PositionerSecondaryAngleIncrement(0x0018, 0x1521);
+ Tag const DetectorPrimaryAngle(0x0018, 0x1530);
+ Tag const DetectorSecondaryAngle(0x0018, 0x1531);
+ Tag const ShutterShape(0x0018, 0x1600);
+ Tag const ShutterLeftVerticalEdge(0x0018, 0x1602);
+ Tag const ShutterRightVerticalEdge(0x0018, 0x1604);
+ Tag const ShutterUpperHorizontalEdge(0x0018, 0x1606);
+ Tag const ShutterLowerHorizontalEdge(0x0018, 0x1608);
+ Tag const CenterOfCircularShutter(0x0018, 0x1610);
+ Tag const RadiusOfCircularShutter(0x0018, 0x1612);
+ Tag const VerticesOfThePolygonalShutter(0x0018, 0x1620);
+ Tag const ShutterPresentationValue(0x0018, 0x1622);
+ Tag const ShutterOverlayGroup(0x0018, 0x1623);
+ Tag const ShutterPresentationColorCIELabValue(0x0018, 0x1624);
+ Tag const CollimatorShape(0x0018, 0x1700);
+ Tag const CollimatorLeftVerticalEdge(0x0018, 0x1702);
+ Tag const CollimatorRightVerticalEdge(0x0018, 0x1704);
+ Tag const CollimatorUpperHorizontalEdge(0x0018, 0x1706);
+ Tag const CollimatorLowerHorizontalEdge(0x0018, 0x1708);
+ Tag const CenterOfCircularCollimator(0x0018, 0x1710);
+ Tag const RadiusOfCircularCollimator(0x0018, 0x1712);
+ Tag const VerticesOfThePolygonalCollimator(0x0018, 0x1720);
+ Tag const AcquisitionTimeSynchronized(0x0018, 0x1800);
+ Tag const TimeSource(0x0018, 0x1801);
+ Tag const TimeDistributionProtocol(0x0018, 0x1802);
+ Tag const NTPSourceAddress(0x0018, 0x1803);
+ Tag const PageNumberVector(0x0018, 0x2001);
+ Tag const FrameLabelVector(0x0018, 0x2002);
+ Tag const FramePrimaryAngleVector(0x0018, 0x2003);
+ Tag const FrameSecondaryAngleVector(0x0018, 0x2004);
+ Tag const SliceLocationVector(0x0018, 0x2005);
+ Tag const DisplayWindowLabelVector(0x0018, 0x2006);
+ Tag const NominalScannedPixelSpacing(0x0018, 0x2010);
+ Tag const DigitizingDeviceTransportDirection(0x0018, 0x2020);
+ Tag const RotationOfScannedFilm(0x0018, 0x2030);
+ Tag const BiopsyTargetSequence(0x0018, 0x2041);
+ Tag const TargetUID(0x0018, 0x2042);
+ Tag const LocalizingCursorPosition(0x0018, 0x2043);
+ Tag const CalculatedTargetPosition(0x0018, 0x2044);
+ Tag const TargetLabel(0x0018, 0x2045);
+ Tag const DisplayedZValue(0x0018, 0x2046);
+ Tag const IVUSAcquisition(0x0018, 0x3100);
+ Tag const IVUSPullbackRate(0x0018, 0x3101);
+ Tag const IVUSGatedRate(0x0018, 0x3102);
+ Tag const IVUSPullbackStartFrameNumber(0x0018, 0x3103);
+ Tag const IVUSPullbackStopFrameNumber(0x0018, 0x3104);
+ Tag const LesionNumber(0x0018, 0x3105);
+ Tag const AcquisitionComments(0x0018, 0x4000);
+ Tag const OutputPower(0x0018, 0x5000);
+ Tag const TransducerData(0x0018, 0x5010);
+ Tag const FocusDepth(0x0018, 0x5012);
+ Tag const ProcessingFunction(0x0018, 0x5020);
+ Tag const PostprocessingFunction(0x0018, 0x5021);
+ Tag const MechanicalIndex(0x0018, 0x5022);
+ Tag const BoneThermalIndex(0x0018, 0x5024);
+ Tag const CranialThermalIndex(0x0018, 0x5026);
+ Tag const SoftTissueThermalIndex(0x0018, 0x5027);
+ Tag const SoftTissueFocusThermalIndex(0x0018, 0x5028);
+ Tag const SoftTissueSurfaceThermalIndex(0x0018, 0x5029);
+ Tag const DynamicRange(0x0018, 0x5030);
+ Tag const TotalGain(0x0018, 0x5040);
+ Tag const DepthOfScanField(0x0018, 0x5050);
+ Tag const PatientPosition(0x0018, 0x5100);
+ Tag const ViewPosition(0x0018, 0x5101);
+ Tag const ProjectionEponymousNameCodeSequence(0x0018, 0x5104);
+ Tag const ImageTransformationMatrix(0x0018, 0x5210);
+ Tag const ImageTranslationVector(0x0018, 0x5212);
+ Tag const Sensitivity(0x0018, 0x6000);
+ Tag const SequenceOfUltrasoundRegions(0x0018, 0x6011);
+ Tag const RegionSpatialFormat(0x0018, 0x6012);
+ Tag const RegionDataType(0x0018, 0x6014);
+ Tag const RegionFlags(0x0018, 0x6016);
+ Tag const RegionLocationMinX0(0x0018, 0x6018);
+ Tag const RegionLocationMinY0(0x0018, 0x601a);
+ Tag const RegionLocationMaxX1(0x0018, 0x601c);
+ Tag const RegionLocationMaxY1(0x0018, 0x601e);
+ Tag const ReferencePixelX0(0x0018, 0x6020);
+ Tag const ReferencePixelY0(0x0018, 0x6022);
+ Tag const PhysicalUnitsXDirection(0x0018, 0x6024);
+ Tag const PhysicalUnitsYDirection(0x0018, 0x6026);
+ Tag const ReferencePixelPhysicalValueX(0x0018, 0x6028);
+ Tag const ReferencePixelPhysicalValueY(0x0018, 0x602a);
+ Tag const PhysicalDeltaX(0x0018, 0x602c);
+ Tag const PhysicalDeltaY(0x0018, 0x602e);
+ Tag const TransducerFrequency(0x0018, 0x6030);
+ Tag const TransducerType(0x0018, 0x6031);
+ Tag const PulseRepetitionFrequency(0x0018, 0x6032);
+ Tag const DopplerCorrectionAngle(0x0018, 0x6034);
+ Tag const SteeringAngle(0x0018, 0x6036);
+ Tag const DopplerSampleVolumeXPositionRetired(0x0018, 0x6038);
+ Tag const DopplerSampleVolumeXPosition(0x0018, 0x6039);
+ Tag const DopplerSampleVolumeYPositionRetired(0x0018, 0x603a);
+ Tag const DopplerSampleVolumeYPosition(0x0018, 0x603b);
+ Tag const TMLinePositionX0Retired(0x0018, 0x603c);
+ Tag const TMLinePositionX0(0x0018, 0x603d);
+ Tag const TMLinePositionY0Retired(0x0018, 0x603e);
+ Tag const TMLinePositionY0(0x0018, 0x603f);
+ Tag const TMLinePositionX1Retired(0x0018, 0x6040);
+ Tag const TMLinePositionX1(0x0018, 0x6041);
+ Tag const TMLinePositionY1Retired(0x0018, 0x6042);
+ Tag const TMLinePositionY1(0x0018, 0x6043);
+ Tag const PixelComponentOrganization(0x0018, 0x6044);
+ Tag const PixelComponentMask(0x0018, 0x6046);
+ Tag const PixelComponentRangeStart(0x0018, 0x6048);
+ Tag const PixelComponentRangeStop(0x0018, 0x604a);
+ Tag const PixelComponentPhysicalUnits(0x0018, 0x604c);
+ Tag const PixelComponentDataType(0x0018, 0x604e);
+ Tag const NumberOfTableBreakPoints(0x0018, 0x6050);
+ Tag const TableOfXBreakPoints(0x0018, 0x6052);
+ Tag const TableOfYBreakPoints(0x0018, 0x6054);
+ Tag const NumberOfTableEntries(0x0018, 0x6056);
+ Tag const TableOfPixelValues(0x0018, 0x6058);
+ Tag const TableOfParameterValues(0x0018, 0x605a);
+ Tag const RWaveTimeVector(0x0018, 0x6060);
+ Tag const DetectorConditionsNominalFlag(0x0018, 0x7000);
+ Tag const DetectorTemperature(0x0018, 0x7001);
+ Tag const DetectorType(0x0018, 0x7004);
+ Tag const DetectorConfiguration(0x0018, 0x7005);
+ Tag const DetectorDescription(0x0018, 0x7006);
+ Tag const DetectorMode(0x0018, 0x7008);
+ Tag const DetectorID(0x0018, 0x700a);
+ Tag const DateOfLastDetectorCalibration(0x0018, 0x700c);
+ Tag const TimeOfLastDetectorCalibration(0x0018, 0x700e);
+ Tag const ExposuresOnDetectorSinceLastCalibration(0x0018, 0x7010);
+ Tag const ExposuresOnDetectorSinceManufactured(0x0018, 0x7011);
+ Tag const DetectorTimeSinceLastExposure(0x0018, 0x7012);
+ Tag const DetectorActiveTime(0x0018, 0x7014);
+ Tag const DetectorActivationOffsetFromExposure(0x0018, 0x7016);
+ Tag const DetectorBinning(0x0018, 0x701a);
+ Tag const DetectorElementPhysicalSize(0x0018, 0x7020);
+ Tag const DetectorElementSpacing(0x0018, 0x7022);
+ Tag const DetectorActiveShape(0x0018, 0x7024);
+ Tag const DetectorActiveDimensions(0x0018, 0x7026);
+ Tag const DetectorActiveOrigin(0x0018, 0x7028);
+ Tag const DetectorManufacturerName(0x0018, 0x702a);
+ Tag const DetectorManufacturerModelName(0x0018, 0x702b);
+ Tag const FieldOfViewOrigin(0x0018, 0x7030);
+ Tag const FieldOfViewRotation(0x0018, 0x7032);
+ Tag const FieldOfViewHorizontalFlip(0x0018, 0x7034);
+ Tag const PixelDataAreaOriginRelativeToFOV(0x0018, 0x7036);
+ Tag const PixelDataAreaRotationAngleRelativeToFOV(0x0018, 0x7038);
+ Tag const GridAbsorbingMaterial(0x0018, 0x7040);
+ Tag const GridSpacingMaterial(0x0018, 0x7041);
+ Tag const GridThickness(0x0018, 0x7042);
+ Tag const GridPitch(0x0018, 0x7044);
+ Tag const GridAspectRatio(0x0018, 0x7046);
+ Tag const GridPeriod(0x0018, 0x7048);
+ Tag const GridFocalDistance(0x0018, 0x704c);
+ Tag const FilterMaterial(0x0018, 0x7050);
+ Tag const FilterThicknessMinimum(0x0018, 0x7052);
+ Tag const FilterThicknessMaximum(0x0018, 0x7054);
+ Tag const FilterBeamPathLengthMinimum(0x0018, 0x7056);
+ Tag const FilterBeamPathLengthMaximum(0x0018, 0x7058);
+ Tag const ExposureControlMode(0x0018, 0x7060);
+ Tag const ExposureControlModeDescription(0x0018, 0x7062);
+ Tag const ExposureStatus(0x0018, 0x7064);
+ Tag const PhototimerSetting(0x0018, 0x7065);
+ Tag const ExposureTimeInuS(0x0018, 0x8150);
+ Tag const XRayTubeCurrentInuA(0x0018, 0x8151);
+ Tag const ContentQualification(0x0018, 0x9004);
+ Tag const PulseSequenceName(0x0018, 0x9005);
+ Tag const MRImagingModifierSequence(0x0018, 0x9006);
+ Tag const EchoPulseSequence(0x0018, 0x9008);
+ Tag const InversionRecovery(0x0018, 0x9009);
+ Tag const FlowCompensation(0x0018, 0x9010);
+ Tag const MultipleSpinEcho(0x0018, 0x9011);
+ Tag const MultiPlanarExcitation(0x0018, 0x9012);
+ Tag const PhaseContrast(0x0018, 0x9014);
+ Tag const TimeOfFlightContrast(0x0018, 0x9015);
+ Tag const Spoiling(0x0018, 0x9016);
+ Tag const SteadyStatePulseSequence(0x0018, 0x9017);
+ Tag const EchoPlanarPulseSequence(0x0018, 0x9018);
+ Tag const TagAngleFirstAxis(0x0018, 0x9019);
+ Tag const MagnetizationTransfer(0x0018, 0x9020);
+ Tag const T2Preparation(0x0018, 0x9021);
+ Tag const BloodSignalNulling(0x0018, 0x9022);
+ Tag const SaturationRecovery(0x0018, 0x9024);
+ Tag const SpectrallySelectedSuppression(0x0018, 0x9025);
+ Tag const SpectrallySelectedExcitation(0x0018, 0x9026);
+ Tag const SpatialPresaturation(0x0018, 0x9027);
+ Tag const Tagging(0x0018, 0x9028);
+ Tag const OversamplingPhase(0x0018, 0x9029);
+ Tag const TagSpacingFirstDimension(0x0018, 0x9030);
+ Tag const GeometryOfKSpaceTraversal(0x0018, 0x9032);
+ Tag const SegmentedKSpaceTraversal(0x0018, 0x9033);
+ Tag const RectilinearPhaseEncodeReordering(0x0018, 0x9034);
+ Tag const TagThickness(0x0018, 0x9035);
+ Tag const PartialFourierDirection(0x0018, 0x9036);
+ Tag const CardiacSynchronizationTechnique(0x0018, 0x9037);
+ Tag const ReceiveCoilManufacturerName(0x0018, 0x9041);
+ Tag const MRReceiveCoilSequence(0x0018, 0x9042);
+ Tag const ReceiveCoilType(0x0018, 0x9043);
+ Tag const QuadratureReceiveCoil(0x0018, 0x9044);
+ Tag const MultiCoilDefinitionSequence(0x0018, 0x9045);
+ Tag const MultiCoilConfiguration(0x0018, 0x9046);
+ Tag const MultiCoilElementName(0x0018, 0x9047);
+ Tag const MultiCoilElementUsed(0x0018, 0x9048);
+ Tag const MRTransmitCoilSequence(0x0018, 0x9049);
+ Tag const TransmitCoilManufacturerName(0x0018, 0x9050);
+ Tag const TransmitCoilType(0x0018, 0x9051);
+ Tag const SpectralWidth(0x0018, 0x9052);
+ Tag const ChemicalShiftReference(0x0018, 0x9053);
+ Tag const VolumeLocalizationTechnique(0x0018, 0x9054);
+ Tag const MRAcquisitionFrequencyEncodingSteps(0x0018, 0x9058);
+ Tag const Decoupling(0x0018, 0x9059);
+ Tag const DecoupledNucleus(0x0018, 0x9060);
+ Tag const DecouplingFrequency(0x0018, 0x9061);
+ Tag const DecouplingMethod(0x0018, 0x9062);
+ Tag const DecouplingChemicalShiftReference(0x0018, 0x9063);
+ Tag const KSpaceFiltering(0x0018, 0x9064);
+ Tag const TimeDomainFiltering(0x0018, 0x9065);
+ Tag const NumberOfZeroFills(0x0018, 0x9066);
+ Tag const BaselineCorrection(0x0018, 0x9067);
+ Tag const ParallelReductionFactorInPlane(0x0018, 0x9069);
+ Tag const CardiacRRIntervalSpecified(0x0018, 0x9070);
+ Tag const AcquisitionDuration(0x0018, 0x9073);
+ Tag const FrameAcquisitionDateTime(0x0018, 0x9074);
+ Tag const DiffusionDirectionality(0x0018, 0x9075);
+ Tag const DiffusionGradientDirectionSequence(0x0018, 0x9076);
+ Tag const ParallelAcquisition(0x0018, 0x9077);
+ Tag const ParallelAcquisitionTechnique(0x0018, 0x9078);
+ Tag const InversionTimes(0x0018, 0x9079);
+ Tag const MetaboliteMapDescription(0x0018, 0x9080);
+ Tag const PartialFourier(0x0018, 0x9081);
+ Tag const EffectiveEchoTime(0x0018, 0x9082);
+ Tag const MetaboliteMapCodeSequence(0x0018, 0x9083);
+ Tag const ChemicalShiftSequence(0x0018, 0x9084);
+ Tag const CardiacSignalSource(0x0018, 0x9085);
+ Tag const DiffusionBValue(0x0018, 0x9087);
+ Tag const DiffusionGradientOrientation(0x0018, 0x9089);
+ Tag const VelocityEncodingDirection(0x0018, 0x9090);
+ Tag const VelocityEncodingMinimumValue(0x0018, 0x9091);
+ Tag const VelocityEncodingAcquisitionSequence(0x0018, 0x9092);
+ Tag const NumberOfKSpaceTrajectories(0x0018, 0x9093);
+ Tag const CoverageOfKSpace(0x0018, 0x9094);
+ Tag const SpectroscopyAcquisitionPhaseRows(0x0018, 0x9095);
+ Tag const ParallelReductionFactorInPlaneRetired(0x0018, 0x9096);
+ Tag const TransmitterFrequency(0x0018, 0x9098);
+ Tag const ResonantNucleus(0x0018, 0x9100);
+ Tag const FrequencyCorrection(0x0018, 0x9101);
+ Tag const MRSpectroscopyFOVGeometrySequence(0x0018, 0x9103);
+ Tag const SlabThickness(0x0018, 0x9104);
+ Tag const SlabOrientation(0x0018, 0x9105);
+ Tag const MidSlabPosition(0x0018, 0x9106);
+ Tag const MRSpatialSaturationSequence(0x0018, 0x9107);
+ Tag const MRTimingAndRelatedParametersSequence(0x0018, 0x9112);
+ Tag const MREchoSequence(0x0018, 0x9114);
+ Tag const MRModifierSequence(0x0018, 0x9115);
+ Tag const MRDiffusionSequence(0x0018, 0x9117);
+ Tag const CardiacSynchronizationSequence(0x0018, 0x9118);
+ Tag const MRAveragesSequence(0x0018, 0x9119);
+ Tag const MRFOVGeometrySequence(0x0018, 0x9125);
+ Tag const VolumeLocalizationSequence(0x0018, 0x9126);
+ Tag const SpectroscopyAcquisitionDataColumns(0x0018, 0x9127);
+ Tag const DiffusionAnisotropyType(0x0018, 0x9147);
+ Tag const FrameReferenceDateTime(0x0018, 0x9151);
+ Tag const MRMetaboliteMapSequence(0x0018, 0x9152);
+ Tag const ParallelReductionFactorOutOfPlane(0x0018, 0x9155);
+ Tag const SpectroscopyAcquisitionOutOfPlanePhaseSteps(0x0018, 0x9159);
+ Tag const BulkMotionStatus(0x0018, 0x9166);
+ Tag const ParallelReductionFactorSecondInPlane(0x0018, 0x9168);
+ Tag const CardiacBeatRejectionTechnique(0x0018, 0x9169);
+ Tag const RespiratoryMotionCompensationTechnique(0x0018, 0x9170);
+ Tag const RespiratorySignalSource(0x0018, 0x9171);
+ Tag const BulkMotionCompensationTechnique(0x0018, 0x9172);
+ Tag const BulkMotionSignalSource(0x0018, 0x9173);
+ Tag const ApplicableSafetyStandardAgency(0x0018, 0x9174);
+ Tag const ApplicableSafetyStandardDescription(0x0018, 0x9175);
+ Tag const OperatingModeSequence(0x0018, 0x9176);
+ Tag const OperatingModeType(0x0018, 0x9177);
+ Tag const OperatingMode(0x0018, 0x9178);
+ Tag const SpecificAbsorptionRateDefinition(0x0018, 0x9179);
+ Tag const GradientOutputType(0x0018, 0x9180);
+ Tag const SpecificAbsorptionRateValue(0x0018, 0x9181);
+ Tag const GradientOutput(0x0018, 0x9182);
+ Tag const FlowCompensationDirection(0x0018, 0x9183);
+ Tag const TaggingDelay(0x0018, 0x9184);
+ Tag const RespiratoryMotionCompensationTechniqueDescription(0x0018, 0x9185);
+ Tag const RespiratorySignalSourceID(0x0018, 0x9186);
+ Tag const ChemicalShiftMinimumIntegrationLimitInHz(0x0018, 0x9195);
+ Tag const ChemicalShiftMaximumIntegrationLimitInHz(0x0018, 0x9196);
+ Tag const MRVelocityEncodingSequence(0x0018, 0x9197);
+ Tag const FirstOrderPhaseCorrection(0x0018, 0x9198);
+ Tag const WaterReferencedPhaseCorrection(0x0018, 0x9199);
+ Tag const MRSpectroscopyAcquisitionType(0x0018, 0x9200);
+ Tag const RespiratoryCyclePosition(0x0018, 0x9214);
+ Tag const VelocityEncodingMaximumValue(0x0018, 0x9217);
+ Tag const TagSpacingSecondDimension(0x0018, 0x9218);
+ Tag const TagAngleSecondAxis(0x0018, 0x9219);
+ Tag const FrameAcquisitionDuration(0x0018, 0x9220);
+ Tag const MRImageFrameTypeSequence(0x0018, 0x9226);
+ Tag const MRSpectroscopyFrameTypeSequence(0x0018, 0x9227);
+ Tag const MRAcquisitionPhaseEncodingStepsInPlane(0x0018, 0x9231);
+ Tag const MRAcquisitionPhaseEncodingStepsOutOfPlane(0x0018, 0x9232);
+ Tag const SpectroscopyAcquisitionPhaseColumns(0x0018, 0x9234);
+ Tag const CardiacCyclePosition(0x0018, 0x9236);
+ Tag const SpecificAbsorptionRateSequence(0x0018, 0x9239);
+ Tag const RFEchoTrainLength(0x0018, 0x9240);
+ Tag const GradientEchoTrainLength(0x0018, 0x9241);
+ Tag const ArterialSpinLabelingContrast(0x0018, 0x9250);
+ Tag const MRArterialSpinLabelingSequence(0x0018, 0x9251);
+ Tag const ASLTechniqueDescription(0x0018, 0x9252);
+ Tag const ASLSlabNumber(0x0018, 0x9253);
+ Tag const ASLSlabThickness(0x0018, 0x9254);
+ Tag const ASLSlabOrientation(0x0018, 0x9255);
+ Tag const ASLMidSlabPosition(0x0018, 0x9256);
+ Tag const ASLContext(0x0018, 0x9257);
+ Tag const ASLPulseTrainDuration(0x0018, 0x9258);
+ Tag const ASLCrusherFlag(0x0018, 0x9259);
+ Tag const ASLCrusherFlowLimit(0x0018, 0x925a);
+ Tag const ASLCrusherDescription(0x0018, 0x925b);
+ Tag const ASLBolusCutoffFlag(0x0018, 0x925c);
+ Tag const ASLBolusCutoffTimingSequence(0x0018, 0x925d);
+ Tag const ASLBolusCutoffTechnique(0x0018, 0x925e);
+ Tag const ASLBolusCutoffDelayTime(0x0018, 0x925f);
+ Tag const ASLSlabSequence(0x0018, 0x9260);
+ Tag const ChemicalShiftMinimumIntegrationLimitInppm(0x0018, 0x9295);
+ Tag const ChemicalShiftMaximumIntegrationLimitInppm(0x0018, 0x9296);
+ Tag const WaterReferenceAcquisition(0x0018, 0x9297);
+ Tag const EchoPeakPosition(0x0018, 0x9298);
+ Tag const CTAcquisitionTypeSequence(0x0018, 0x9301);
+ Tag const AcquisitionType(0x0018, 0x9302);
+ Tag const TubeAngle(0x0018, 0x9303);
+ Tag const CTAcquisitionDetailsSequence(0x0018, 0x9304);
+ Tag const RevolutionTime(0x0018, 0x9305);
+ Tag const SingleCollimationWidth(0x0018, 0x9306);
+ Tag const TotalCollimationWidth(0x0018, 0x9307);
+ Tag const CTTableDynamicsSequence(0x0018, 0x9308);
+ Tag const TableSpeed(0x0018, 0x9309);
+ Tag const TableFeedPerRotation(0x0018, 0x9310);
+ Tag const SpiralPitchFactor(0x0018, 0x9311);
+ Tag const CTGeometrySequence(0x0018, 0x9312);
+ Tag const DataCollectionCenterPatient(0x0018, 0x9313);
+ Tag const CTReconstructionSequence(0x0018, 0x9314);
+ Tag const ReconstructionAlgorithm(0x0018, 0x9315);
+ Tag const ConvolutionKernelGroup(0x0018, 0x9316);
+ Tag const ReconstructionFieldOfView(0x0018, 0x9317);
+ Tag const ReconstructionTargetCenterPatient(0x0018, 0x9318);
+ Tag const ReconstructionAngle(0x0018, 0x9319);
+ Tag const ImageFilter(0x0018, 0x9320);
+ Tag const CTExposureSequence(0x0018, 0x9321);
+ Tag const ReconstructionPixelSpacing(0x0018, 0x9322);
+ Tag const ExposureModulationType(0x0018, 0x9323);
+ Tag const EstimatedDoseSaving(0x0018, 0x9324);
+ Tag const CTXRayDetailsSequence(0x0018, 0x9325);
+ Tag const CTPositionSequence(0x0018, 0x9326);
+ Tag const TablePosition(0x0018, 0x9327);
+ Tag const ExposureTimeInms(0x0018, 0x9328);
+ Tag const CTImageFrameTypeSequence(0x0018, 0x9329);
+ Tag const XRayTubeCurrentInmA(0x0018, 0x9330);
+ Tag const ExposureInmAs(0x0018, 0x9332);
+ Tag const ConstantVolumeFlag(0x0018, 0x9333);
+ Tag const FluoroscopyFlag(0x0018, 0x9334);
+ Tag const DistanceSourceToDataCollectionCenter(0x0018, 0x9335);
+ Tag const ContrastBolusAgentNumber(0x0018, 0x9337);
+ Tag const ContrastBolusIngredientCodeSequence(0x0018, 0x9338);
+ Tag const ContrastAdministrationProfileSequence(0x0018, 0x9340);
+ Tag const ContrastBolusUsageSequence(0x0018, 0x9341);
+ Tag const ContrastBolusAgentAdministered(0x0018, 0x9342);
+ Tag const ContrastBolusAgentDetected(0x0018, 0x9343);
+ Tag const ContrastBolusAgentPhase(0x0018, 0x9344);
+ Tag const CTDIvol(0x0018, 0x9345);
+ Tag const CTDIPhantomTypeCodeSequence(0x0018, 0x9346);
+ Tag const CalciumScoringMassFactorPatient(0x0018, 0x9351);
+ Tag const CalciumScoringMassFactorDevice(0x0018, 0x9352);
+ Tag const EnergyWeightingFactor(0x0018, 0x9353);
+ Tag const CTAdditionalXRaySourceSequence(0x0018, 0x9360);
+ Tag const ProjectionPixelCalibrationSequence(0x0018, 0x9401);
+ Tag const DistanceSourceToIsocenter(0x0018, 0x9402);
+ Tag const DistanceObjectToTableTop(0x0018, 0x9403);
+ Tag const ObjectPixelSpacingInCenterOfBeam(0x0018, 0x9404);
+ Tag const PositionerPositionSequence(0x0018, 0x9405);
+ Tag const TablePositionSequence(0x0018, 0x9406);
+ Tag const CollimatorShapeSequence(0x0018, 0x9407);
+ Tag const PlanesInAcquisition(0x0018, 0x9410);
+ Tag const XAXRFFrameCharacteristicsSequence(0x0018, 0x9412);
+ Tag const FrameAcquisitionSequence(0x0018, 0x9417);
+ Tag const XRayReceptorType(0x0018, 0x9420);
+ Tag const AcquisitionProtocolName(0x0018, 0x9423);
+ Tag const AcquisitionProtocolDescription(0x0018, 0x9424);
+ Tag const ContrastBolusIngredientOpaque(0x0018, 0x9425);
+ Tag const DistanceReceptorPlaneToDetectorHousing(0x0018, 0x9426);
+ Tag const IntensifierActiveShape(0x0018, 0x9427);
+ Tag const IntensifierActiveDimensions(0x0018, 0x9428);
+ Tag const PhysicalDetectorSize(0x0018, 0x9429);
+ Tag const PositionOfIsocenterProjection(0x0018, 0x9430);
+ Tag const FieldOfViewSequence(0x0018, 0x9432);
+ Tag const FieldOfViewDescription(0x0018, 0x9433);
+ Tag const ExposureControlSensingRegionsSequence(0x0018, 0x9434);
+ Tag const ExposureControlSensingRegionShape(0x0018, 0x9435);
+ Tag const ExposureControlSensingRegionLeftVerticalEdge(0x0018, 0x9436);
+ Tag const ExposureControlSensingRegionRightVerticalEdge(0x0018, 0x9437);
+ Tag const ExposureControlSensingRegionUpperHorizontalEdge(0x0018, 0x9438);
+ Tag const ExposureControlSensingRegionLowerHorizontalEdge(0x0018, 0x9439);
+ Tag const CenterOfCircularExposureControlSensingRegion(0x0018, 0x9440);
+ Tag const RadiusOfCircularExposureControlSensingRegion(0x0018, 0x9441);
+ Tag const VerticesOfThePolygonalExposureControlSensingRegion(0x0018, 0x9442);
+ Tag const ColumnAngulationPatient(0x0018, 0x9447);
+ Tag const BeamAngle(0x0018, 0x9449);
+ Tag const FrameDetectorParametersSequence(0x0018, 0x9451);
+ Tag const CalculatedAnatomyThickness(0x0018, 0x9452);
+ Tag const CalibrationSequence(0x0018, 0x9455);
+ Tag const ObjectThicknessSequence(0x0018, 0x9456);
+ Tag const PlaneIdentification(0x0018, 0x9457);
+ Tag const FieldOfViewDimensionsInFloat(0x0018, 0x9461);
+ Tag const IsocenterReferenceSystemSequence(0x0018, 0x9462);
+ Tag const PositionerIsocenterPrimaryAngle(0x0018, 0x9463);
+ Tag const PositionerIsocenterSecondaryAngle(0x0018, 0x9464);
+ Tag const PositionerIsocenterDetectorRotationAngle(0x0018, 0x9465);
+ Tag const TableXPositionToIsocenter(0x0018, 0x9466);
+ Tag const TableYPositionToIsocenter(0x0018, 0x9467);
+ Tag const TableZPositionToIsocenter(0x0018, 0x9468);
+ Tag const TableHorizontalRotationAngle(0x0018, 0x9469);
+ Tag const TableHeadTiltAngle(0x0018, 0x9470);
+ Tag const TableCradleTiltAngle(0x0018, 0x9471);
+ Tag const FrameDisplayShutterSequence(0x0018, 0x9472);
+ Tag const AcquiredImageAreaDoseProduct(0x0018, 0x9473);
+ Tag const CArmPositionerTabletopRelationship(0x0018, 0x9474);
+ Tag const XRayGeometrySequence(0x0018, 0x9476);
+ Tag const IrradiationEventIdentificationSequence(0x0018, 0x9477);
+ Tag const XRay3DFrameTypeSequence(0x0018, 0x9504);
+ Tag const ContributingSourcesSequence(0x0018, 0x9506);
+ Tag const XRay3DAcquisitionSequence(0x0018, 0x9507);
+ Tag const PrimaryPositionerScanArc(0x0018, 0x9508);
+ Tag const SecondaryPositionerScanArc(0x0018, 0x9509);
+ Tag const PrimaryPositionerScanStartAngle(0x0018, 0x9510);
+ Tag const SecondaryPositionerScanStartAngle(0x0018, 0x9511);
+ Tag const PrimaryPositionerIncrement(0x0018, 0x9514);
+ Tag const SecondaryPositionerIncrement(0x0018, 0x9515);
+ Tag const StartAcquisitionDateTime(0x0018, 0x9516);
+ Tag const EndAcquisitionDateTime(0x0018, 0x9517);
+ Tag const PrimaryPositionerIncrementSign(0x0018, 0x9518);
+ Tag const SecondaryPositionerIncrementSign(0x0018, 0x9519);
+ Tag const ApplicationName(0x0018, 0x9524);
+ Tag const ApplicationVersion(0x0018, 0x9525);
+ Tag const ApplicationManufacturer(0x0018, 0x9526);
+ Tag const AlgorithmType(0x0018, 0x9527);
+ Tag const AlgorithmDescription(0x0018, 0x9528);
+ Tag const XRay3DReconstructionSequence(0x0018, 0x9530);
+ Tag const ReconstructionDescription(0x0018, 0x9531);
+ Tag const PerProjectionAcquisitionSequence(0x0018, 0x9538);
+ Tag const DetectorPositionSequence(0x0018, 0x9541);
+ Tag const XRayAcquisitionDoseSequence(0x0018, 0x9542);
+ Tag const XRaySourceIsocenterPrimaryAngle(0x0018, 0x9543);
+ Tag const XRaySourceIsocenterSecondaryAngle(0x0018, 0x9544);
+ Tag const BreastSupportIsocenterPrimaryAngle(0x0018, 0x9545);
+ Tag const BreastSupportIsocenterSecondaryAngle(0x0018, 0x9546);
+ Tag const BreastSupportXPositionToIsocenter(0x0018, 0x9547);
+ Tag const BreastSupportYPositionToIsocenter(0x0018, 0x9548);
+ Tag const BreastSupportZPositionToIsocenter(0x0018, 0x9549);
+ Tag const DetectorIsocenterPrimaryAngle(0x0018, 0x9550);
+ Tag const DetectorIsocenterSecondaryAngle(0x0018, 0x9551);
+ Tag const DetectorXPositionToIsocenter(0x0018, 0x9552);
+ Tag const DetectorYPositionToIsocenter(0x0018, 0x9553);
+ Tag const DetectorZPositionToIsocenter(0x0018, 0x9554);
+ Tag const XRayGridSequence(0x0018, 0x9555);
+ Tag const XRayFilterSequence(0x0018, 0x9556);
+ Tag const DetectorActiveAreaTLHCPosition(0x0018, 0x9557);
+ Tag const DetectorActiveAreaOrientation(0x0018, 0x9558);
+ Tag const PositionerPrimaryAngleDirection(0x0018, 0x9559);
+ Tag const DiffusionBMatrixSequence(0x0018, 0x9601);
+ Tag const DiffusionBValueXX(0x0018, 0x9602);
+ Tag const DiffusionBValueXY(0x0018, 0x9603);
+ Tag const DiffusionBValueXZ(0x0018, 0x9604);
+ Tag const DiffusionBValueYY(0x0018, 0x9605);
+ Tag const DiffusionBValueYZ(0x0018, 0x9606);
+ Tag const DiffusionBValueZZ(0x0018, 0x9607);
+ Tag const DecayCorrectionDateTime(0x0018, 0x9701);
+ Tag const StartDensityThreshold(0x0018, 0x9715);
+ Tag const StartRelativeDensityDifferenceThreshold(0x0018, 0x9716);
+ Tag const StartCardiacTriggerCountThreshold(0x0018, 0x9717);
+ Tag const StartRespiratoryTriggerCountThreshold(0x0018, 0x9718);
+ Tag const TerminationCountsThreshold(0x0018, 0x9719);
+ Tag const TerminationDensityThreshold(0x0018, 0x9720);
+ Tag const TerminationRelativeDensityThreshold(0x0018, 0x9721);
+ Tag const TerminationTimeThreshold(0x0018, 0x9722);
+ Tag const TerminationCardiacTriggerCountThreshold(0x0018, 0x9723);
+ Tag const TerminationRespiratoryTriggerCountThreshold(0x0018, 0x9724);
+ Tag const DetectorGeometry(0x0018, 0x9725);
+ Tag const TransverseDetectorSeparation(0x0018, 0x9726);
+ Tag const AxialDetectorDimension(0x0018, 0x9727);
+ Tag const RadiopharmaceuticalAgentNumber(0x0018, 0x9729);
+ Tag const PETFrameAcquisitionSequence(0x0018, 0x9732);
+ Tag const PETDetectorMotionDetailsSequence(0x0018, 0x9733);
+ Tag const PETTableDynamicsSequence(0x0018, 0x9734);
+ Tag const PETPositionSequence(0x0018, 0x9735);
+ Tag const PETFrameCorrectionFactorsSequence(0x0018, 0x9736);
+ Tag const RadiopharmaceuticalUsageSequence(0x0018, 0x9737);
+ Tag const AttenuationCorrectionSource(0x0018, 0x9738);
+ Tag const NumberOfIterations(0x0018, 0x9739);
+ Tag const NumberOfSubsets(0x0018, 0x9740);
+ Tag const PETReconstructionSequence(0x0018, 0x9749);
+ Tag const PETFrameTypeSequence(0x0018, 0x9751);
+ Tag const TimeOfFlightInformationUsed(0x0018, 0x9755);
+ Tag const ReconstructionType(0x0018, 0x9756);
+ Tag const DecayCorrected(0x0018, 0x9758);
+ Tag const AttenuationCorrected(0x0018, 0x9759);
+ Tag const ScatterCorrected(0x0018, 0x9760);
+ Tag const DeadTimeCorrected(0x0018, 0x9761);
+ Tag const GantryMotionCorrected(0x0018, 0x9762);
+ Tag const PatientMotionCorrected(0x0018, 0x9763);
+ Tag const CountLossNormalizationCorrected(0x0018, 0x9764);
+ Tag const RandomsCorrected(0x0018, 0x9765);
+ Tag const NonUniformRadialSamplingCorrected(0x0018, 0x9766);
+ Tag const SensitivityCalibrated(0x0018, 0x9767);
+ Tag const DetectorNormalizationCorrection(0x0018, 0x9768);
+ Tag const IterativeReconstructionMethod(0x0018, 0x9769);
+ Tag const AttenuationCorrectionTemporalRelationship(0x0018, 0x9770);
+ Tag const PatientPhysiologicalStateSequence(0x0018, 0x9771);
+ Tag const PatientPhysiologicalStateCodeSequence(0x0018, 0x9772);
+ Tag const DepthsOfFocus(0x0018, 0x9801);
+ Tag const ExcludedIntervalsSequence(0x0018, 0x9803);
+ Tag const ExclusionStartDateTime(0x0018, 0x9804);
+ Tag const ExclusionDuration(0x0018, 0x9805);
+ Tag const USImageDescriptionSequence(0x0018, 0x9806);
+ Tag const ImageDataTypeSequence(0x0018, 0x9807);
+ Tag const DataType(0x0018, 0x9808);
+ Tag const TransducerScanPatternCodeSequence(0x0018, 0x9809);
+ Tag const AliasedDataType(0x0018, 0x980b);
+ Tag const PositionMeasuringDeviceUsed(0x0018, 0x980c);
+ Tag const TransducerGeometryCodeSequence(0x0018, 0x980d);
+ Tag const TransducerBeamSteeringCodeSequence(0x0018, 0x980e);
+ Tag const TransducerApplicationCodeSequence(0x0018, 0x980f);
+ Tag const ZeroVelocityPixelValue(0x0018, 0x9810);
+ Tag const ContributingEquipmentSequence(0x0018, 0xa001);
+ Tag const ContributionDateTime(0x0018, 0xa002);
+ Tag const ContributionDescription(0x0018, 0xa003);
+ Tag const StudyInstanceUID(0x0020, 0x000d);
+ Tag const SeriesInstanceUID(0x0020, 0x000e);
+ Tag const StudyID(0x0020, 0x0010);
+ Tag const SeriesNumber(0x0020, 0x0011);
+ Tag const AcquisitionNumber(0x0020, 0x0012);
+ Tag const InstanceNumber(0x0020, 0x0013);
+ Tag const IsotopeNumber(0x0020, 0x0014);
+ Tag const PhaseNumber(0x0020, 0x0015);
+ Tag const IntervalNumber(0x0020, 0x0016);
+ Tag const TimeSlotNumber(0x0020, 0x0017);
+ Tag const AngleNumber(0x0020, 0x0018);
+ Tag const ItemNumber(0x0020, 0x0019);
+ Tag const PatientOrientation(0x0020, 0x0020);
+ Tag const OverlayNumber(0x0020, 0x0022);
+ Tag const CurveNumber(0x0020, 0x0024);
+ Tag const LUTNumber(0x0020, 0x0026);
+ Tag const ImagePosition(0x0020, 0x0030);
+ Tag const ImagePositionPatient(0x0020, 0x0032);
+ Tag const ImageOrientation(0x0020, 0x0035);
+ Tag const ImageOrientationPatient(0x0020, 0x0037);
+ Tag const Location(0x0020, 0x0050);
+ Tag const FrameOfReferenceUID(0x0020, 0x0052);
+ Tag const Laterality(0x0020, 0x0060);
+ Tag const ImageLaterality(0x0020, 0x0062);
+ Tag const ImageGeometryType(0x0020, 0x0070);
+ Tag const MaskingImage(0x0020, 0x0080);
+ Tag const ReportNumber(0x0020, 0x00aa);
+ Tag const TemporalPositionIdentifier(0x0020, 0x0100);
+ Tag const NumberOfTemporalPositions(0x0020, 0x0105);
+ Tag const TemporalResolution(0x0020, 0x0110);
+ Tag const SynchronizationFrameOfReferenceUID(0x0020, 0x0200);
+ Tag const SOPInstanceUIDOfConcatenationSource(0x0020, 0x0242);
+ Tag const SeriesInStudy(0x0020, 0x1000);
+ Tag const AcquisitionsInSeries(0x0020, 0x1001);
+ Tag const ImagesInAcquisition(0x0020, 0x1002);
+ Tag const ImagesInSeries(0x0020, 0x1003);
+ Tag const AcquisitionsInStudy(0x0020, 0x1004);
+ Tag const ImagesInStudy(0x0020, 0x1005);
+ Tag const Reference(0x0020, 0x1020);
+ Tag const PositionReferenceIndicator(0x0020, 0x1040);
+ Tag const SliceLocation(0x0020, 0x1041);
+ Tag const OtherStudyNumbers(0x0020, 0x1070);
+ Tag const NumberOfPatientRelatedStudies(0x0020, 0x1200);
+ Tag const NumberOfPatientRelatedSeries(0x0020, 0x1202);
+ Tag const NumberOfPatientRelatedInstances(0x0020, 0x1204);
+ Tag const NumberOfStudyRelatedSeries(0x0020, 0x1206);
+ Tag const NumberOfStudyRelatedInstances(0x0020, 0x1208);
+ Tag const NumberOfSeriesRelatedInstances(0x0020, 0x1209);
+ Tag const ModifyingDeviceID(0x0020, 0x3401);
+ Tag const ModifiedImageID(0x0020, 0x3402);
+ Tag const ModifiedImageDate(0x0020, 0x3403);
+ Tag const ModifyingDeviceManufacturer(0x0020, 0x3404);
+ Tag const ModifiedImageTime(0x0020, 0x3405);
+ Tag const ModifiedImageDescription(0x0020, 0x3406);
+ Tag const ImageComments(0x0020, 0x4000);
+ Tag const OriginalImageIdentification(0x0020, 0x5000);
+ Tag const OriginalImageIdentificationNomenclature(0x0020, 0x5002);
+ Tag const StackID(0x0020, 0x9056);
+ Tag const InStackPositionNumber(0x0020, 0x9057);
+ Tag const FrameAnatomySequence(0x0020, 0x9071);
+ Tag const FrameLaterality(0x0020, 0x9072);
+ Tag const FrameContentSequence(0x0020, 0x9111);
+ Tag const PlanePositionSequence(0x0020, 0x9113);
+ Tag const PlaneOrientationSequence(0x0020, 0x9116);
+ Tag const TemporalPositionIndex(0x0020, 0x9128);
+ Tag const NominalCardiacTriggerDelayTime(0x0020, 0x9153);
+ Tag const NominalCardiacTriggerTimePriorToRPeak(0x0020, 0x9154);
+ Tag const ActualCardiacTriggerTimePriorToRPeak(0x0020, 0x9155);
+ Tag const FrameAcquisitionNumber(0x0020, 0x9156);
+ Tag const DimensionIndexValues(0x0020, 0x9157);
+ Tag const FrameComments(0x0020, 0x9158);
+ Tag const ConcatenationUID(0x0020, 0x9161);
+ Tag const InConcatenationNumber(0x0020, 0x9162);
+ Tag const InConcatenationTotalNumber(0x0020, 0x9163);
+ Tag const DimensionOrganizationUID(0x0020, 0x9164);
+ Tag const DimensionIndexPointer(0x0020, 0x9165);
+ Tag const FunctionalGroupPointer(0x0020, 0x9167);
+ Tag const UnassignedSharedConvertedAttributesSequence(0x0020, 0x9170);
+ Tag const UnassignedPerFrameConvertedAttributesSequence(0x0020, 0x9171);
+ Tag const ConversionSourceAttributesSequence(0x0020, 0x9172);
+ Tag const DimensionIndexPrivateCreator(0x0020, 0x9213);
+ Tag const DimensionOrganizationSequence(0x0020, 0x9221);
+ Tag const DimensionIndexSequence(0x0020, 0x9222);
+ Tag const ConcatenationFrameOffsetNumber(0x0020, 0x9228);
+ Tag const FunctionalGroupPrivateCreator(0x0020, 0x9238);
+ Tag const NominalPercentageOfCardiacPhase(0x0020, 0x9241);
+ Tag const NominalPercentageOfRespiratoryPhase(0x0020, 0x9245);
+ Tag const StartingRespiratoryAmplitude(0x0020, 0x9246);
+ Tag const StartingRespiratoryPhase(0x0020, 0x9247);
+ Tag const EndingRespiratoryAmplitude(0x0020, 0x9248);
+ Tag const EndingRespiratoryPhase(0x0020, 0x9249);
+ Tag const RespiratoryTriggerType(0x0020, 0x9250);
+ Tag const RRIntervalTimeNominal(0x0020, 0x9251);
+ Tag const ActualCardiacTriggerDelayTime(0x0020, 0x9252);
+ Tag const RespiratorySynchronizationSequence(0x0020, 0x9253);
+ Tag const RespiratoryIntervalTime(0x0020, 0x9254);
+ Tag const NominalRespiratoryTriggerDelayTime(0x0020, 0x9255);
+ Tag const RespiratoryTriggerDelayThreshold(0x0020, 0x9256);
+ Tag const ActualRespiratoryTriggerDelayTime(0x0020, 0x9257);
+ Tag const ImagePositionVolume(0x0020, 0x9301);
+ Tag const ImageOrientationVolume(0x0020, 0x9302);
+ Tag const UltrasoundAcquisitionGeometry(0x0020, 0x9307);
+ Tag const ApexPosition(0x0020, 0x9308);
+ Tag const VolumeToTransducerMappingMatrix(0x0020, 0x9309);
+ Tag const VolumeToTableMappingMatrix(0x0020, 0x930a);
+ Tag const VolumeToTransducerRelationship(0x0020, 0x930b);
+ Tag const PatientFrameOfReferenceSource(0x0020, 0x930c);
+ Tag const TemporalPositionTimeOffset(0x0020, 0x930d);
+ Tag const PlanePositionVolumeSequence(0x0020, 0x930e);
+ Tag const PlaneOrientationVolumeSequence(0x0020, 0x930f);
+ Tag const TemporalPositionSequence(0x0020, 0x9310);
+ Tag const DimensionOrganizationType(0x0020, 0x9311);
+ Tag const VolumeFrameOfReferenceUID(0x0020, 0x9312);
+ Tag const TableFrameOfReferenceUID(0x0020, 0x9313);
+ Tag const DimensionDescriptionLabel(0x0020, 0x9421);
+ Tag const PatientOrientationInFrameSequence(0x0020, 0x9450);
+ Tag const FrameLabel(0x0020, 0x9453);
+ Tag const AcquisitionIndex(0x0020, 0x9518);
+ Tag const ContributingSOPInstancesReferenceSequence(0x0020, 0x9529);
+ Tag const ReconstructionIndex(0x0020, 0x9536);
+ Tag const LightPathFilterPassThroughWavelength(0x0022, 0x0001);
+ Tag const LightPathFilterPassBand(0x0022, 0x0002);
+ Tag const ImagePathFilterPassThroughWavelength(0x0022, 0x0003);
+ Tag const ImagePathFilterPassBand(0x0022, 0x0004);
+ Tag const PatientEyeMovementCommanded(0x0022, 0x0005);
+ Tag const PatientEyeMovementCommandCodeSequence(0x0022, 0x0006);
+ Tag const SphericalLensPower(0x0022, 0x0007);
+ Tag const CylinderLensPower(0x0022, 0x0008);
+ Tag const CylinderAxis(0x0022, 0x0009);
+ Tag const EmmetropicMagnification(0x0022, 0x000a);
+ Tag const IntraOcularPressure(0x0022, 0x000b);
+ Tag const HorizontalFieldOfView(0x0022, 0x000c);
+ Tag const PupilDilated(0x0022, 0x000d);
+ Tag const DegreeOfDilation(0x0022, 0x000e);
+ Tag const StereoBaselineAngle(0x0022, 0x0010);
+ Tag const StereoBaselineDisplacement(0x0022, 0x0011);
+ Tag const StereoHorizontalPixelOffset(0x0022, 0x0012);
+ Tag const StereoVerticalPixelOffset(0x0022, 0x0013);
+ Tag const StereoRotation(0x0022, 0x0014);
+ Tag const AcquisitionDeviceTypeCodeSequence(0x0022, 0x0015);
+ Tag const IlluminationTypeCodeSequence(0x0022, 0x0016);
+ Tag const LightPathFilterTypeStackCodeSequence(0x0022, 0x0017);
+ Tag const ImagePathFilterTypeStackCodeSequence(0x0022, 0x0018);
+ Tag const LensesCodeSequence(0x0022, 0x0019);
+ Tag const ChannelDescriptionCodeSequence(0x0022, 0x001a);
+ Tag const RefractiveStateSequence(0x0022, 0x001b);
+ Tag const MydriaticAgentCodeSequence(0x0022, 0x001c);
+ Tag const RelativeImagePositionCodeSequence(0x0022, 0x001d);
+ Tag const CameraAngleOfView(0x0022, 0x001e);
+ Tag const StereoPairsSequence(0x0022, 0x0020);
+ Tag const LeftImageSequence(0x0022, 0x0021);
+ Tag const RightImageSequence(0x0022, 0x0022);
+ Tag const AxialLengthOfTheEye(0x0022, 0x0030);
+ Tag const OphthalmicFrameLocationSequence(0x0022, 0x0031);
+ Tag const ReferenceCoordinates(0x0022, 0x0032);
+ Tag const DepthSpatialResolution(0x0022, 0x0035);
+ Tag const MaximumDepthDistortion(0x0022, 0x0036);
+ Tag const AlongScanSpatialResolution(0x0022, 0x0037);
+ Tag const MaximumAlongScanDistortion(0x0022, 0x0038);
+ Tag const OphthalmicImageOrientation(0x0022, 0x0039);
+ Tag const DepthOfTransverseImage(0x0022, 0x0041);
+ Tag const MydriaticAgentConcentrationUnitsSequence(0x0022, 0x0042);
+ Tag const AcrossScanSpatialResolution(0x0022, 0x0048);
+ Tag const MaximumAcrossScanDistortion(0x0022, 0x0049);
+ Tag const MydriaticAgentConcentration(0x0022, 0x004e);
+ Tag const IlluminationWaveLength(0x0022, 0x0055);
+ Tag const IlluminationPower(0x0022, 0x0056);
+ Tag const IlluminationBandwidth(0x0022, 0x0057);
+ Tag const MydriaticAgentSequence(0x0022, 0x0058);
+ Tag const OphthalmicAxialMeasurementsRightEyeSequence(0x0022, 0x1007);
+ Tag const OphthalmicAxialMeasurementsLeftEyeSequence(0x0022, 0x1008);
+ Tag const OphthalmicAxialMeasurementsDeviceType(0x0022, 0x1009);
+ Tag const OphthalmicAxialLengthMeasurementsType(0x0022, 0x1010);
+ Tag const OphthalmicAxialLengthSequence(0x0022, 0x1012);
+ Tag const OphthalmicAxialLength(0x0022, 0x1019);
+ Tag const LensStatusCodeSequence(0x0022, 0x1024);
+ Tag const VitreousStatusCodeSequence(0x0022, 0x1025);
+ Tag const IOLFormulaCodeSequence(0x0022, 0x1028);
+ Tag const IOLFormulaDetail(0x0022, 0x1029);
+ Tag const KeratometerIndex(0x0022, 0x1033);
+ Tag const SourceOfOphthalmicAxialLengthCodeSequence(0x0022, 0x1035);
+ Tag const TargetRefraction(0x0022, 0x1037);
+ Tag const RefractiveProcedureOccurred(0x0022, 0x1039);
+ Tag const RefractiveSurgeryTypeCodeSequence(0x0022, 0x1040);
+ Tag const OphthalmicUltrasoundMethodCodeSequence(0x0022, 0x1044);
+ Tag const OphthalmicAxialLengthMeasurementsSequence(0x0022, 0x1050);
+ Tag const IOLPower(0x0022, 0x1053);
+ Tag const PredictedRefractiveError(0x0022, 0x1054);
+ Tag const OphthalmicAxialLengthVelocity(0x0022, 0x1059);
+ Tag const LensStatusDescription(0x0022, 0x1065);
+ Tag const VitreousStatusDescription(0x0022, 0x1066);
+ Tag const IOLPowerSequence(0x0022, 0x1090);
+ Tag const LensConstantSequence(0x0022, 0x1092);
+ Tag const IOLManufacturer(0x0022, 0x1093);
+ Tag const LensConstantDescription(0x0022, 0x1094);
+ Tag const ImplantName(0x0022, 0x1095);
+ Tag const KeratometryMeasurementTypeCodeSequence(0x0022, 0x1096);
+ Tag const ImplantPartNumber(0x0022, 0x1097);
+ Tag const ReferencedOphthalmicAxialMeasurementsSequence(0x0022, 0x1100);
+ Tag const OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence(0x0022, 0x1101);
+ Tag const RefractiveErrorBeforeRefractiveSurgeryCodeSequence(0x0022, 0x1103);
+ Tag const IOLPowerForExactEmmetropia(0x0022, 0x1121);
+ Tag const IOLPowerForExactTargetRefraction(0x0022, 0x1122);
+ Tag const AnteriorChamberDepthDefinitionCodeSequence(0x0022, 0x1125);
+ Tag const LensThicknessSequence(0x0022, 0x1127);
+ Tag const AnteriorChamberDepthSequence(0x0022, 0x1128);
+ Tag const LensThickness(0x0022, 0x1130);
+ Tag const AnteriorChamberDepth(0x0022, 0x1131);
+ Tag const SourceOfLensThicknessDataCodeSequence(0x0022, 0x1132);
+ Tag const SourceOfAnteriorChamberDepthDataCodeSequence(0x0022, 0x1133);
+ Tag const SourceOfRefractiveMeasurementsSequence(0x0022, 0x1134);
+ Tag const SourceOfRefractiveMeasurementsCodeSequence(0x0022, 0x1135);
+ Tag const OphthalmicAxialLengthMeasurementModified(0x0022, 0x1140);
+ Tag const OphthalmicAxialLengthDataSourceCodeSequence(0x0022, 0x1150);
+ Tag const OphthalmicAxialLengthAcquisitionMethodCodeSequence(0x0022, 0x1153);
+ Tag const SignalToNoiseRatio(0x0022, 0x1155);
+ Tag const OphthalmicAxialLengthDataSourceDescription(0x0022, 0x1159);
+ Tag const OphthalmicAxialLengthMeasurementsTotalLengthSequence(0x0022, 0x1210);
+ Tag const OphthalmicAxialLengthMeasurementsSegmentalLengthSequence(0x0022, 0x1211);
+ Tag const OphthalmicAxialLengthMeasurementsLengthSummationSequence(0x0022, 0x1212);
+ Tag const UltrasoundOphthalmicAxialLengthMeasurementsSequence(0x0022, 0x1220);
+ Tag const OpticalOphthalmicAxialLengthMeasurementsSequence(0x0022, 0x1225);
+ Tag const UltrasoundSelectedOphthalmicAxialLengthSequence(0x0022, 0x1230);
+ Tag const OphthalmicAxialLengthSelectionMethodCodeSequence(0x0022, 0x1250);
+ Tag const OpticalSelectedOphthalmicAxialLengthSequence(0x0022, 0x1255);
+ Tag const SelectedSegmentalOphthalmicAxialLengthSequence(0x0022, 0x1257);
+ Tag const SelectedTotalOphthalmicAxialLengthSequence(0x0022, 0x1260);
+ Tag const OphthalmicAxialLengthQualityMetricSequence(0x0022, 0x1262);
+ Tag const OphthalmicAxialLengthQualityMetricTypeCodeSequence(0x0022, 0x1265);
+ Tag const OphthalmicAxialLengthQualityMetricTypeDescription(0x0022, 0x1273);
+ Tag const IntraocularLensCalculationsRightEyeSequence(0x0022, 0x1300);
+ Tag const IntraocularLensCalculationsLeftEyeSequence(0x0022, 0x1310);
+ Tag const ReferencedOphthalmicAxialLengthMeasurementQCImageSequence(0x0022, 0x1330);
+ Tag const OphthalmicMappingDeviceType(0x0022, 0x1415);
+ Tag const AcquisitionMethodCodeSequence(0x0022, 0x1420);
+ Tag const AcquisitionMethodAlgorithmSequence(0x0022, 0x1423);
+ Tag const OphthalmicThicknessMapTypeCodeSequence(0x0022, 0x1436);
+ Tag const OphthalmicThicknessMappingNormalsSequence(0x0022, 0x1443);
+ Tag const RetinalThicknessDefinitionCodeSequence(0x0022, 0x1445);
+ Tag const PixelValueMappingToCodedConceptSequence(0x0022, 0x1450);
+ Tag const MappedPixelValue(0x0022, 0x1452);
+ Tag const PixelValueMappingExplanation(0x0022, 0x1454);
+ Tag const OphthalmicThicknessMapQualityThresholdSequence(0x0022, 0x1458);
+ Tag const OphthalmicThicknessMapThresholdQualityRating(0x0022, 0x1460);
+ Tag const AnatomicStructureReferencePoint(0x0022, 0x1463);
+ Tag const RegistrationToLocalizerSequence(0x0022, 0x1465);
+ Tag const RegisteredLocalizerUnits(0x0022, 0x1466);
+ Tag const RegisteredLocalizerTopLeftHandCorner(0x0022, 0x1467);
+ Tag const RegisteredLocalizerBottomRightHandCorner(0x0022, 0x1468);
+ Tag const OphthalmicThicknessMapQualityRatingSequence(0x0022, 0x1470);
+ Tag const RelevantOPTAttributesSequence(0x0022, 0x1472);
+ Tag const TransformationMethodCodeSequence(0x0022, 0x1512);
+ Tag const TransformationAlgorithmSequence(0x0022, 0x1513);
+ Tag const OphthalmicAxialLengthMethod(0x0022, 0x1515);
+ Tag const OphthalmicFOV(0x0022, 0x1517);
+ Tag const TwoDimensionalToThreeDimensionalMapSequence(0x0022, 0x1518);
+ Tag const WideFieldOphthalmicPhotographyQualityRatingSequence(0x0022, 0x1525);
+ Tag const WideFieldOphthalmicPhotographyQualityThresholdSequence(0x0022, 0x1526);
+ Tag const WideFieldOphthalmicPhotographyThresholdQualityRating(0x0022, 0x1527);
+ Tag const XCoordinatesCenterPixelViewAngle(0x0022, 0x1528);
+ Tag const YCoordinatesCenterPixelViewAngle(0x0022, 0x1529);
+ Tag const NumberOfMapPoints(0x0022, 0x1530);
+ Tag const TwoDimensionalToThreeDimensionalMapData(0x0022, 0x1531);
+ Tag const VisualFieldHorizontalExtent(0x0024, 0x0010);
+ Tag const VisualFieldVerticalExtent(0x0024, 0x0011);
+ Tag const VisualFieldShape(0x0024, 0x0012);
+ Tag const ScreeningTestModeCodeSequence(0x0024, 0x0016);
+ Tag const MaximumStimulusLuminance(0x0024, 0x0018);
+ Tag const BackgroundLuminance(0x0024, 0x0020);
+ Tag const StimulusColorCodeSequence(0x0024, 0x0021);
+ Tag const BackgroundIlluminationColorCodeSequence(0x0024, 0x0024);
+ Tag const StimulusArea(0x0024, 0x0025);
+ Tag const StimulusPresentationTime(0x0024, 0x0028);
+ Tag const FixationSequence(0x0024, 0x0032);
+ Tag const FixationMonitoringCodeSequence(0x0024, 0x0033);
+ Tag const VisualFieldCatchTrialSequence(0x0024, 0x0034);
+ Tag const FixationCheckedQuantity(0x0024, 0x0035);
+ Tag const PatientNotProperlyFixatedQuantity(0x0024, 0x0036);
+ Tag const PresentedVisualStimuliDataFlag(0x0024, 0x0037);
+ Tag const NumberOfVisualStimuli(0x0024, 0x0038);
+ Tag const ExcessiveFixationLossesDataFlag(0x0024, 0x0039);
+ Tag const ExcessiveFixationLosses(0x0024, 0x0040);
+ Tag const StimuliRetestingQuantity(0x0024, 0x0042);
+ Tag const CommentsOnPatientPerformanceOfVisualField(0x0024, 0x0044);
+ Tag const FalseNegativesEstimateFlag(0x0024, 0x0045);
+ Tag const FalseNegativesEstimate(0x0024, 0x0046);
+ Tag const NegativeCatchTrialsQuantity(0x0024, 0x0048);
+ Tag const FalseNegativesQuantity(0x0024, 0x0050);
+ Tag const ExcessiveFalseNegativesDataFlag(0x0024, 0x0051);
+ Tag const ExcessiveFalseNegatives(0x0024, 0x0052);
+ Tag const FalsePositivesEstimateFlag(0x0024, 0x0053);
+ Tag const FalsePositivesEstimate(0x0024, 0x0054);
+ Tag const CatchTrialsDataFlag(0x0024, 0x0055);
+ Tag const PositiveCatchTrialsQuantity(0x0024, 0x0056);
+ Tag const TestPointNormalsDataFlag(0x0024, 0x0057);
+ Tag const TestPointNormalsSequence(0x0024, 0x0058);
+ Tag const GlobalDeviationProbabilityNormalsFlag(0x0024, 0x0059);
+ Tag const FalsePositivesQuantity(0x0024, 0x0060);
+ Tag const ExcessiveFalsePositivesDataFlag(0x0024, 0x0061);
+ Tag const ExcessiveFalsePositives(0x0024, 0x0062);
+ Tag const VisualFieldTestNormalsFlag(0x0024, 0x0063);
+ Tag const ResultsNormalsSequence(0x0024, 0x0064);
+ Tag const AgeCorrectedSensitivityDeviationAlgorithmSequence(0x0024, 0x0065);
+ Tag const GlobalDeviationFromNormal(0x0024, 0x0066);
+ Tag const GeneralizedDefectSensitivityDeviationAlgorithmSequence(0x0024, 0x0067);
+ Tag const LocalizedDeviationFromNormal(0x0024, 0x0068);
+ Tag const PatientReliabilityIndicator(0x0024, 0x0069);
+ Tag const VisualFieldMeanSensitivity(0x0024, 0x0070);
+ Tag const GlobalDeviationProbability(0x0024, 0x0071);
+ Tag const LocalDeviationProbabilityNormalsFlag(0x0024, 0x0072);
+ Tag const LocalizedDeviationProbability(0x0024, 0x0073);
+ Tag const ShortTermFluctuationCalculated(0x0024, 0x0074);
+ Tag const ShortTermFluctuation(0x0024, 0x0075);
+ Tag const ShortTermFluctuationProbabilityCalculated(0x0024, 0x0076);
+ Tag const ShortTermFluctuationProbability(0x0024, 0x0077);
+ Tag const CorrectedLocalizedDeviationFromNormalCalculated(0x0024, 0x0078);
+ Tag const CorrectedLocalizedDeviationFromNormal(0x0024, 0x0079);
+ Tag const CorrectedLocalizedDeviationFromNormalProbabilityCalculated(0x0024, 0x0080);
+ Tag const CorrectedLocalizedDeviationFromNormalProbability(0x0024, 0x0081);
+ Tag const GlobalDeviationProbabilitySequence(0x0024, 0x0083);
+ Tag const LocalizedDeviationProbabilitySequence(0x0024, 0x0085);
+ Tag const FovealSensitivityMeasured(0x0024, 0x0086);
+ Tag const FovealSensitivity(0x0024, 0x0087);
+ Tag const VisualFieldTestDuration(0x0024, 0x0088);
+ Tag const VisualFieldTestPointSequence(0x0024, 0x0089);
+ Tag const VisualFieldTestPointXCoordinate(0x0024, 0x0090);
+ Tag const VisualFieldTestPointYCoordinate(0x0024, 0x0091);
+ Tag const AgeCorrectedSensitivityDeviationValue(0x0024, 0x0092);
+ Tag const StimulusResults(0x0024, 0x0093);
+ Tag const SensitivityValue(0x0024, 0x0094);
+ Tag const RetestStimulusSeen(0x0024, 0x0095);
+ Tag const RetestSensitivityValue(0x0024, 0x0096);
+ Tag const VisualFieldTestPointNormalsSequence(0x0024, 0x0097);
+ Tag const QuantifiedDefect(0x0024, 0x0098);
+ Tag const AgeCorrectedSensitivityDeviationProbabilityValue(0x0024, 0x0100);
+ Tag const GeneralizedDefectCorrectedSensitivityDeviationFlag(0x0024, 0x0102);
+ Tag const GeneralizedDefectCorrectedSensitivityDeviationValue(0x0024, 0x0103);
+ Tag const GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue(0x0024, 0x0104);
+ Tag const MinimumSensitivityValue(0x0024, 0x0105);
+ Tag const BlindSpotLocalized(0x0024, 0x0106);
+ Tag const BlindSpotXCoordinate(0x0024, 0x0107);
+ Tag const BlindSpotYCoordinate(0x0024, 0x0108);
+ Tag const VisualAcuityMeasurementSequence(0x0024, 0x0110);
+ Tag const RefractiveParametersUsedOnPatientSequence(0x0024, 0x0112);
+ Tag const MeasurementLaterality(0x0024, 0x0113);
+ Tag const OphthalmicPatientClinicalInformationLeftEyeSequence(0x0024, 0x0114);
+ Tag const OphthalmicPatientClinicalInformationRightEyeSequence(0x0024, 0x0115);
+ Tag const FovealPointNormativeDataFlag(0x0024, 0x0117);
+ Tag const FovealPointProbabilityValue(0x0024, 0x0118);
+ Tag const ScreeningBaselineMeasured(0x0024, 0x0120);
+ Tag const ScreeningBaselineMeasuredSequence(0x0024, 0x0122);
+ Tag const ScreeningBaselineType(0x0024, 0x0124);
+ Tag const ScreeningBaselineValue(0x0024, 0x0126);
+ Tag const AlgorithmSource(0x0024, 0x0202);
+ Tag const DataSetName(0x0024, 0x0306);
+ Tag const DataSetVersion(0x0024, 0x0307);
+ Tag const DataSetSource(0x0024, 0x0308);
+ Tag const DataSetDescription(0x0024, 0x0309);
+ Tag const VisualFieldTestReliabilityGlobalIndexSequence(0x0024, 0x0317);
+ Tag const VisualFieldGlobalResultsIndexSequence(0x0024, 0x0320);
+ Tag const DataObservationSequence(0x0024, 0x0325);
+ Tag const IndexNormalsFlag(0x0024, 0x0338);
+ Tag const IndexProbability(0x0024, 0x0341);
+ Tag const IndexProbabilitySequence(0x0024, 0x0344);
+ Tag const SamplesPerPixel(0x0028, 0x0002);
+ Tag const SamplesPerPixelUsed(0x0028, 0x0003);
+ Tag const PhotometricInterpretation(0x0028, 0x0004);
+ Tag const ImageDimensions(0x0028, 0x0005);
+ Tag const PlanarConfiguration(0x0028, 0x0006);
+ Tag const NumberOfFrames(0x0028, 0x0008);
+ Tag const FrameIncrementPointer(0x0028, 0x0009);
+ Tag const FrameDimensionPointer(0x0028, 0x000a);
+ Tag const Rows(0x0028, 0x0010);
+ Tag const Columns(0x0028, 0x0011);
+ Tag const Planes(0x0028, 0x0012);
+ Tag const UltrasoundColorDataPresent(0x0028, 0x0014);
+ Tag const PixelSpacing(0x0028, 0x0030);
+ Tag const ZoomFactor(0x0028, 0x0031);
+ Tag const ZoomCenter(0x0028, 0x0032);
+ Tag const PixelAspectRatio(0x0028, 0x0034);
+ Tag const ImageFormat(0x0028, 0x0040);
+ Tag const ManipulatedImage(0x0028, 0x0050);
+ Tag const CorrectedImage(0x0028, 0x0051);
+ Tag const CompressionRecognitionCode(0x0028, 0x005f);
+ Tag const CompressionCode(0x0028, 0x0060);
+ Tag const CompressionOriginator(0x0028, 0x0061);
+ Tag const CompressionLabel(0x0028, 0x0062);
+ Tag const CompressionDescription(0x0028, 0x0063);
+ Tag const CompressionSequence(0x0028, 0x0065);
+ Tag const CompressionStepPointers(0x0028, 0x0066);
+ Tag const RepeatInterval(0x0028, 0x0068);
+ Tag const BitsGrouped(0x0028, 0x0069);
+ Tag const PerimeterTable(0x0028, 0x0070);
+ Tag const PerimeterValue(0x0028, 0x0071);
+ Tag const PredictorRows(0x0028, 0x0080);
+ Tag const PredictorColumns(0x0028, 0x0081);
+ Tag const PredictorConstants(0x0028, 0x0082);
+ Tag const BlockedPixels(0x0028, 0x0090);
+ Tag const BlockRows(0x0028, 0x0091);
+ Tag const BlockColumns(0x0028, 0x0092);
+ Tag const RowOverlap(0x0028, 0x0093);
+ Tag const ColumnOverlap(0x0028, 0x0094);
+ Tag const BitsAllocated(0x0028, 0x0100);
+ Tag const BitsStored(0x0028, 0x0101);
+ Tag const HighBit(0x0028, 0x0102);
+ Tag const PixelRepresentation(0x0028, 0x0103);
+ Tag const SmallestValidPixelValue(0x0028, 0x0104);
+ Tag const LargestValidPixelValue(0x0028, 0x0105);
+ Tag const SmallestImagePixelValue(0x0028, 0x0106);
+ Tag const LargestImagePixelValue(0x0028, 0x0107);
+ Tag const SmallestPixelValueInSeries(0x0028, 0x0108);
+ Tag const LargestPixelValueInSeries(0x0028, 0x0109);
+ Tag const SmallestImagePixelValueInPlane(0x0028, 0x0110);
+ Tag const LargestImagePixelValueInPlane(0x0028, 0x0111);
+ Tag const PixelPaddingValue(0x0028, 0x0120);
+ Tag const PixelPaddingRangeLimit(0x0028, 0x0121);
+ Tag const FloatPixelPaddingValue(0x0028, 0x0122);
+ Tag const DoubleFloatPixelPaddingValue(0x0028, 0x0123);
+ Tag const FloatPixelPaddingRangeLimit(0x0028, 0x0124);
+ Tag const DoubleFloatPixelPaddingRangeLimit(0x0028, 0x0125);
+ Tag const ImageLocation(0x0028, 0x0200);
+ Tag const QualityControlImage(0x0028, 0x0300);
+ Tag const BurnedInAnnotation(0x0028, 0x0301);
+ Tag const RecognizableVisualFeatures(0x0028, 0x0302);
+ Tag const LongitudinalTemporalInformationModified(0x0028, 0x0303);
+ Tag const ReferencedColorPaletteInstanceUID(0x0028, 0x0304);
+ Tag const TransformLabel(0x0028, 0x0400);
+ Tag const TransformVersionNumber(0x0028, 0x0401);
+ Tag const NumberOfTransformSteps(0x0028, 0x0402);
+ Tag const SequenceOfCompressedData(0x0028, 0x0403);
+ Tag const DetailsOfCoefficients(0x0028, 0x0404);
+ Tag const DCTLabel(0x0028, 0x0700);
+ Tag const DataBlockDescription(0x0028, 0x0701);
+ Tag const DataBlock(0x0028, 0x0702);
+ Tag const NormalizationFactorFormat(0x0028, 0x0710);
+ Tag const ZonalMapNumberFormat(0x0028, 0x0720);
+ Tag const ZonalMapLocation(0x0028, 0x0721);
+ Tag const ZonalMapFormat(0x0028, 0x0722);
+ Tag const AdaptiveMapFormat(0x0028, 0x0730);
+ Tag const CodeNumberFormat(0x0028, 0x0740);
+ Tag const PixelSpacingCalibrationType(0x0028, 0x0a02);
+ Tag const PixelSpacingCalibrationDescription(0x0028, 0x0a04);
+ Tag const PixelIntensityRelationship(0x0028, 0x1040);
+ Tag const PixelIntensityRelationshipSign(0x0028, 0x1041);
+ Tag const WindowCenter(0x0028, 0x1050);
+ Tag const WindowWidth(0x0028, 0x1051);
+ Tag const RescaleIntercept(0x0028, 0x1052);
+ Tag const RescaleSlope(0x0028, 0x1053);
+ Tag const RescaleType(0x0028, 0x1054);
+ Tag const WindowCenterWidthExplanation(0x0028, 0x1055);
+ Tag const VOILUTFunction(0x0028, 0x1056);
+ Tag const GrayScale(0x0028, 0x1080);
+ Tag const RecommendedViewingMode(0x0028, 0x1090);
+ Tag const GrayLookupTableDescriptor(0x0028, 0x1100);
+ Tag const RedPaletteColorLookupTableDescriptor(0x0028, 0x1101);
+ Tag const GreenPaletteColorLookupTableDescriptor(0x0028, 0x1102);
+ Tag const BluePaletteColorLookupTableDescriptor(0x0028, 0x1103);
+ Tag const AlphaPaletteColorLookupTableDescriptor(0x0028, 0x1104);
+ Tag const LargeRedPaletteColorLookupTableDescriptor(0x0028, 0x1111);
+ Tag const LargeGreenPaletteColorLookupTableDescriptor(0x0028, 0x1112);
+ Tag const LargeBluePaletteColorLookupTableDescriptor(0x0028, 0x1113);
+ Tag const PaletteColorLookupTableUID(0x0028, 0x1199);
+ Tag const GrayLookupTableData(0x0028, 0x1200);
+ Tag const RedPaletteColorLookupTableData(0x0028, 0x1201);
+ Tag const GreenPaletteColorLookupTableData(0x0028, 0x1202);
+ Tag const BluePaletteColorLookupTableData(0x0028, 0x1203);
+ Tag const AlphaPaletteColorLookupTableData(0x0028, 0x1204);
+ Tag const LargeRedPaletteColorLookupTableData(0x0028, 0x1211);
+ Tag const LargeGreenPaletteColorLookupTableData(0x0028, 0x1212);
+ Tag const LargeBluePaletteColorLookupTableData(0x0028, 0x1213);
+ Tag const LargePaletteColorLookupTableUID(0x0028, 0x1214);
+ Tag const SegmentedRedPaletteColorLookupTableData(0x0028, 0x1221);
+ Tag const SegmentedGreenPaletteColorLookupTableData(0x0028, 0x1222);
+ Tag const SegmentedBluePaletteColorLookupTableData(0x0028, 0x1223);
+ Tag const BreastImplantPresent(0x0028, 0x1300);
+ Tag const PartialView(0x0028, 0x1350);
+ Tag const PartialViewDescription(0x0028, 0x1351);
+ Tag const PartialViewCodeSequence(0x0028, 0x1352);
+ Tag const SpatialLocationsPreserved(0x0028, 0x135a);
+ Tag const DataFrameAssignmentSequence(0x0028, 0x1401);
+ Tag const DataPathAssignment(0x0028, 0x1402);
+ Tag const BitsMappedToColorLookupTable(0x0028, 0x1403);
+ Tag const BlendingLUT1Sequence(0x0028, 0x1404);
+ Tag const BlendingLUT1TransferFunction(0x0028, 0x1405);
+ Tag const BlendingWeightConstant(0x0028, 0x1406);
+ Tag const BlendingLookupTableDescriptor(0x0028, 0x1407);
+ Tag const BlendingLookupTableData(0x0028, 0x1408);
+ Tag const EnhancedPaletteColorLookupTableSequence(0x0028, 0x140b);
+ Tag const BlendingLUT2Sequence(0x0028, 0x140c);
+ Tag const BlendingLUT2TransferFunction(0x0028, 0x140d);
+ Tag const DataPathID(0x0028, 0x140e);
+ Tag const RGBLUTTransferFunction(0x0028, 0x140f);
+ Tag const AlphaLUTTransferFunction(0x0028, 0x1410);
+ Tag const ICCProfile(0x0028, 0x2000);
+ Tag const LossyImageCompression(0x0028, 0x2110);
+ Tag const LossyImageCompressionRatio(0x0028, 0x2112);
+ Tag const LossyImageCompressionMethod(0x0028, 0x2114);
+ Tag const ModalityLUTSequence(0x0028, 0x3000);
+ Tag const LUTDescriptor(0x0028, 0x3002);
+ Tag const LUTExplanation(0x0028, 0x3003);
+ Tag const ModalityLUTType(0x0028, 0x3004);
+ Tag const LUTData(0x0028, 0x3006);
+ Tag const VOILUTSequence(0x0028, 0x3010);
+ Tag const SoftcopyVOILUTSequence(0x0028, 0x3110);
+ Tag const ImagePresentationComments(0x0028, 0x4000);
+ Tag const BiPlaneAcquisitionSequence(0x0028, 0x5000);
+ Tag const RepresentativeFrameNumber(0x0028, 0x6010);
+ Tag const FrameNumbersOfInterest(0x0028, 0x6020);
+ Tag const FrameOfInterestDescription(0x0028, 0x6022);
+ Tag const FrameOfInterestType(0x0028, 0x6023);
+ Tag const MaskPointers(0x0028, 0x6030);
+ Tag const RWavePointer(0x0028, 0x6040);
+ Tag const MaskSubtractionSequence(0x0028, 0x6100);
+ Tag const MaskOperation(0x0028, 0x6101);
+ Tag const ApplicableFrameRange(0x0028, 0x6102);
+ Tag const MaskFrameNumbers(0x0028, 0x6110);
+ Tag const ContrastFrameAveraging(0x0028, 0x6112);
+ Tag const MaskSubPixelShift(0x0028, 0x6114);
+ Tag const TIDOffset(0x0028, 0x6120);
+ Tag const MaskOperationExplanation(0x0028, 0x6190);
+ Tag const EquipmentAdministratorSequence(0x0028, 0x7000);
+ Tag const NumberOfDisplaySubsystems(0x0028, 0x7001);
+ Tag const CurrentConfigurationID(0x0028, 0x7002);
+ Tag const DisplaySubsystemID(0x0028, 0x7003);
+ Tag const DisplaySubsystemName(0x0028, 0x7004);
+ Tag const DisplaySubsystemDescription(0x0028, 0x7005);
+ Tag const SystemStatus(0x0028, 0x7006);
+ Tag const SystemStatusComment(0x0028, 0x7007);
+ Tag const TargetLuminanceCharacteristicsSequence(0x0028, 0x7008);
+ Tag const LuminanceCharacteristicsID(0x0028, 0x7009);
+ Tag const DisplaySubsystemConfigurationSequence(0x0028, 0x700a);
+ Tag const ConfigurationID(0x0028, 0x700b);
+ Tag const ConfigurationName(0x0028, 0x700c);
+ Tag const ConfigurationDescription(0x0028, 0x700d);
+ Tag const ReferencedTargetLuminanceCharacteristicsID(0x0028, 0x700e);
+ Tag const QAResultsSequence(0x0028, 0x700f);
+ Tag const DisplaySubsystemQAResultsSequence(0x0028, 0x7010);
+ Tag const ConfigurationQAResultsSequence(0x0028, 0x7011);
+ Tag const MeasurementEquipmentSequence(0x0028, 0x7012);
+ Tag const MeasurementFunctions(0x0028, 0x7013);
+ Tag const MeasurementEquipmentType(0x0028, 0x7014);
+ Tag const VisualEvaluationResultSequence(0x0028, 0x7015);
+ Tag const DisplayCalibrationResultSequence(0x0028, 0x7016);
+ Tag const DDLValue(0x0028, 0x7017);
+ Tag const CIExyWhitePoint(0x0028, 0x7018);
+ Tag const DisplayFunctionType(0x0028, 0x7019);
+ Tag const GammaValue(0x0028, 0x701a);
+ Tag const NumberOfLuminancePoints(0x0028, 0x701b);
+ Tag const LuminanceResponseSequence(0x0028, 0x701c);
+ Tag const TargetMinimumLuminance(0x0028, 0x701d);
+ Tag const TargetMaximumLuminance(0x0028, 0x701e);
+ Tag const LuminanceValue(0x0028, 0x701f);
+ Tag const LuminanceResponseDescription(0x0028, 0x7020);
+ Tag const WhitePointFlag(0x0028, 0x7021);
+ Tag const DisplayDeviceTypeCodeSequence(0x0028, 0x7022);
+ Tag const DisplaySubsystemSequence(0x0028, 0x7023);
+ Tag const LuminanceResultSequence(0x0028, 0x7024);
+ Tag const AmbientLightValueSource(0x0028, 0x7025);
+ Tag const MeasuredCharacteristics(0x0028, 0x7026);
+ Tag const LuminanceUniformityResultSequence(0x0028, 0x7027);
+ Tag const VisualEvaluationTestSequence(0x0028, 0x7028);
+ Tag const TestResult(0x0028, 0x7029);
+ Tag const TestResultComment(0x0028, 0x702a);
+ Tag const TestImageValidation(0x0028, 0x702b);
+ Tag const TestPatternCodeSequence(0x0028, 0x702c);
+ Tag const MeasurementPatternCodeSequence(0x0028, 0x702d);
+ Tag const VisualEvaluationMethodCodeSequence(0x0028, 0x702e);
+ Tag const PixelDataProviderURL(0x0028, 0x7fe0);
+ Tag const DataPointRows(0x0028, 0x9001);
+ Tag const DataPointColumns(0x0028, 0x9002);
+ Tag const SignalDomainColumns(0x0028, 0x9003);
+ Tag const LargestMonochromePixelValue(0x0028, 0x9099);
+ Tag const DataRepresentation(0x0028, 0x9108);
+ Tag const PixelMeasuresSequence(0x0028, 0x9110);
+ Tag const FrameVOILUTSequence(0x0028, 0x9132);
+ Tag const PixelValueTransformationSequence(0x0028, 0x9145);
+ Tag const SignalDomainRows(0x0028, 0x9235);
+ Tag const DisplayFilterPercentage(0x0028, 0x9411);
+ Tag const FramePixelShiftSequence(0x0028, 0x9415);
+ Tag const SubtractionItemID(0x0028, 0x9416);
+ Tag const PixelIntensityRelationshipLUTSequence(0x0028, 0x9422);
+ Tag const FramePixelDataPropertiesSequence(0x0028, 0x9443);
+ Tag const GeometricalProperties(0x0028, 0x9444);
+ Tag const GeometricMaximumDistortion(0x0028, 0x9445);
+ Tag const ImageProcessingApplied(0x0028, 0x9446);
+ Tag const MaskSelectionMode(0x0028, 0x9454);
+ Tag const LUTFunction(0x0028, 0x9474);
+ Tag const MaskVisibilityPercentage(0x0028, 0x9478);
+ Tag const PixelShiftSequence(0x0028, 0x9501);
+ Tag const RegionPixelShiftSequence(0x0028, 0x9502);
+ Tag const VerticesOfTheRegion(0x0028, 0x9503);
+ Tag const MultiFramePresentationSequence(0x0028, 0x9505);
+ Tag const PixelShiftFrameRange(0x0028, 0x9506);
+ Tag const LUTFrameRange(0x0028, 0x9507);
+ Tag const ImageToEquipmentMappingMatrix(0x0028, 0x9520);
+ Tag const EquipmentCoordinateSystemIdentification(0x0028, 0x9537);
+ Tag const StudyStatusID(0x0032, 0x000a);
+ Tag const StudyPriorityID(0x0032, 0x000c);
+ Tag const StudyIDIssuer(0x0032, 0x0012);
+ Tag const StudyVerifiedDate(0x0032, 0x0032);
+ Tag const StudyVerifiedTime(0x0032, 0x0033);
+ Tag const StudyReadDate(0x0032, 0x0034);
+ Tag const StudyReadTime(0x0032, 0x0035);
+ Tag const ScheduledStudyStartDate(0x0032, 0x1000);
+ Tag const ScheduledStudyStartTime(0x0032, 0x1001);
+ Tag const ScheduledStudyStopDate(0x0032, 0x1010);
+ Tag const ScheduledStudyStopTime(0x0032, 0x1011);
+ Tag const ScheduledStudyLocation(0x0032, 0x1020);
+ Tag const ScheduledStudyLocationAETitle(0x0032, 0x1021);
+ Tag const ReasonForStudy(0x0032, 0x1030);
+ Tag const RequestingPhysicianIdentificationSequence(0x0032, 0x1031);
+ Tag const RequestingPhysician(0x0032, 0x1032);
+ Tag const RequestingService(0x0032, 0x1033);
+ Tag const RequestingServiceCodeSequence(0x0032, 0x1034);
+ Tag const StudyArrivalDate(0x0032, 0x1040);
+ Tag const StudyArrivalTime(0x0032, 0x1041);
+ Tag const StudyCompletionDate(0x0032, 0x1050);
+ Tag const StudyCompletionTime(0x0032, 0x1051);
+ Tag const StudyComponentStatusID(0x0032, 0x1055);
+ Tag const RequestedProcedureDescription(0x0032, 0x1060);
+ Tag const RequestedProcedureCodeSequence(0x0032, 0x1064);
+ Tag const RequestedContrastAgent(0x0032, 0x1070);
+ Tag const StudyComments(0x0032, 0x4000);
+ Tag const ReferencedPatientAliasSequence(0x0038, 0x0004);
+ Tag const VisitStatusID(0x0038, 0x0008);
+ Tag const AdmissionID(0x0038, 0x0010);
+ Tag const IssuerOfAdmissionID(0x0038, 0x0011);
+ Tag const IssuerOfAdmissionIDSequence(0x0038, 0x0014);
+ Tag const RouteOfAdmissions(0x0038, 0x0016);
+ Tag const ScheduledAdmissionDate(0x0038, 0x001a);
+ Tag const ScheduledAdmissionTime(0x0038, 0x001b);
+ Tag const ScheduledDischargeDate(0x0038, 0x001c);
+ Tag const ScheduledDischargeTime(0x0038, 0x001d);
+ Tag const ScheduledPatientInstitutionResidence(0x0038, 0x001e);
+ Tag const AdmittingDate(0x0038, 0x0020);
+ Tag const AdmittingTime(0x0038, 0x0021);
+ Tag const DischargeDate(0x0038, 0x0030);
+ Tag const DischargeTime(0x0038, 0x0032);
+ Tag const DischargeDiagnosisDescription(0x0038, 0x0040);
+ Tag const DischargeDiagnosisCodeSequence(0x0038, 0x0044);
+ Tag const SpecialNeeds(0x0038, 0x0050);
+ Tag const ServiceEpisodeID(0x0038, 0x0060);
+ Tag const IssuerOfServiceEpisodeID(0x0038, 0x0061);
+ Tag const ServiceEpisodeDescription(0x0038, 0x0062);
+ Tag const IssuerOfServiceEpisodeIDSequence(0x0038, 0x0064);
+ Tag const PertinentDocumentsSequence(0x0038, 0x0100);
+ Tag const PertinentResourcesSequence(0x0038, 0x0101);
+ Tag const ResourceDescription(0x0038, 0x0102);
+ Tag const CurrentPatientLocation(0x0038, 0x0300);
+ Tag const PatientInstitutionResidence(0x0038, 0x0400);
+ Tag const PatientState(0x0038, 0x0500);
+ Tag const PatientClinicalTrialParticipationSequence(0x0038, 0x0502);
+ Tag const VisitComments(0x0038, 0x4000);
+ Tag const WaveformOriginality(0x003a, 0x0004);
+ Tag const NumberOfWaveformChannels(0x003a, 0x0005);
+ Tag const NumberOfWaveformSamples(0x003a, 0x0010);
+ Tag const SamplingFrequency(0x003a, 0x001a);
+ Tag const MultiplexGroupLabel(0x003a, 0x0020);
+ Tag const ChannelDefinitionSequence(0x003a, 0x0200);
+ Tag const WaveformChannelNumber(0x003a, 0x0202);
+ Tag const ChannelLabel(0x003a, 0x0203);
+ Tag const ChannelStatus(0x003a, 0x0205);
+ Tag const ChannelSourceSequence(0x003a, 0x0208);
+ Tag const ChannelSourceModifiersSequence(0x003a, 0x0209);
+ Tag const SourceWaveformSequence(0x003a, 0x020a);
+ Tag const ChannelDerivationDescription(0x003a, 0x020c);
+ Tag const ChannelSensitivity(0x003a, 0x0210);
+ Tag const ChannelSensitivityUnitsSequence(0x003a, 0x0211);
+ Tag const ChannelSensitivityCorrectionFactor(0x003a, 0x0212);
+ Tag const ChannelBaseline(0x003a, 0x0213);
+ Tag const ChannelTimeSkew(0x003a, 0x0214);
+ Tag const ChannelSampleSkew(0x003a, 0x0215);
+ Tag const ChannelOffset(0x003a, 0x0218);
+ Tag const WaveformBitsStored(0x003a, 0x021a);
+ Tag const FilterLowFrequency(0x003a, 0x0220);
+ Tag const FilterHighFrequency(0x003a, 0x0221);
+ Tag const NotchFilterFrequency(0x003a, 0x0222);
+ Tag const NotchFilterBandwidth(0x003a, 0x0223);
+ Tag const WaveformDataDisplayScale(0x003a, 0x0230);
+ Tag const WaveformDisplayBackgroundCIELabValue(0x003a, 0x0231);
+ Tag const WaveformPresentationGroupSequence(0x003a, 0x0240);
+ Tag const PresentationGroupNumber(0x003a, 0x0241);
+ Tag const ChannelDisplaySequence(0x003a, 0x0242);
+ Tag const ChannelRecommendedDisplayCIELabValue(0x003a, 0x0244);
+ Tag const ChannelPosition(0x003a, 0x0245);
+ Tag const DisplayShadingFlag(0x003a, 0x0246);
+ Tag const FractionalChannelDisplayScale(0x003a, 0x0247);
+ Tag const AbsoluteChannelDisplayScale(0x003a, 0x0248);
+ Tag const MultiplexedAudioChannelsDescriptionCodeSequence(0x003a, 0x0300);
+ Tag const ChannelIdentificationCode(0x003a, 0x0301);
+ Tag const ChannelMode(0x003a, 0x0302);
+ Tag const ScheduledStationAETitle(0x0040, 0x0001);
+ Tag const ScheduledProcedureStepStartDate(0x0040, 0x0002);
+ Tag const ScheduledProcedureStepStartTime(0x0040, 0x0003);
+ Tag const ScheduledProcedureStepEndDate(0x0040, 0x0004);
+ Tag const ScheduledProcedureStepEndTime(0x0040, 0x0005);
+ Tag const ScheduledPerformingPhysicianName(0x0040, 0x0006);
+ Tag const ScheduledProcedureStepDescription(0x0040, 0x0007);
+ Tag const ScheduledProtocolCodeSequence(0x0040, 0x0008);
+ Tag const ScheduledProcedureStepID(0x0040, 0x0009);
+ Tag const StageCodeSequence(0x0040, 0x000a);
+ Tag const ScheduledPerformingPhysicianIdentificationSequence(0x0040, 0x000b);
+ Tag const ScheduledStationName(0x0040, 0x0010);
+ Tag const ScheduledProcedureStepLocation(0x0040, 0x0011);
+ Tag const PreMedication(0x0040, 0x0012);
+ Tag const ScheduledProcedureStepStatus(0x0040, 0x0020);
+ Tag const OrderPlacerIdentifierSequence(0x0040, 0x0026);
+ Tag const OrderFillerIdentifierSequence(0x0040, 0x0027);
+ Tag const LocalNamespaceEntityID(0x0040, 0x0031);
+ Tag const UniversalEntityID(0x0040, 0x0032);
+ Tag const UniversalEntityIDType(0x0040, 0x0033);
+ Tag const IdentifierTypeCode(0x0040, 0x0035);
+ Tag const AssigningFacilitySequence(0x0040, 0x0036);
+ Tag const AssigningJurisdictionCodeSequence(0x0040, 0x0039);
+ Tag const AssigningAgencyOrDepartmentCodeSequence(0x0040, 0x003a);
+ Tag const ScheduledProcedureStepSequence(0x0040, 0x0100);
+ Tag const ReferencedNonImageCompositeSOPInstanceSequence(0x0040, 0x0220);
+ Tag const PerformedStationAETitle(0x0040, 0x0241);
+ Tag const PerformedStationName(0x0040, 0x0242);
+ Tag const PerformedLocation(0x0040, 0x0243);
+ Tag const PerformedProcedureStepStartDate(0x0040, 0x0244);
+ Tag const PerformedProcedureStepStartTime(0x0040, 0x0245);
+ Tag const PerformedProcedureStepEndDate(0x0040, 0x0250);
+ Tag const PerformedProcedureStepEndTime(0x0040, 0x0251);
+ Tag const PerformedProcedureStepStatus(0x0040, 0x0252);
+ Tag const PerformedProcedureStepID(0x0040, 0x0253);
+ Tag const PerformedProcedureStepDescription(0x0040, 0x0254);
+ Tag const PerformedProcedureTypeDescription(0x0040, 0x0255);
+ Tag const PerformedProtocolCodeSequence(0x0040, 0x0260);
+ Tag const PerformedProtocolType(0x0040, 0x0261);
+ Tag const ScheduledStepAttributesSequence(0x0040, 0x0270);
+ Tag const RequestAttributesSequence(0x0040, 0x0275);
+ Tag const CommentsOnThePerformedProcedureStep(0x0040, 0x0280);
+ Tag const PerformedProcedureStepDiscontinuationReasonCodeSequence(0x0040, 0x0281);
+ Tag const QuantitySequence(0x0040, 0x0293);
+ Tag const Quantity(0x0040, 0x0294);
+ Tag const MeasuringUnitsSequence(0x0040, 0x0295);
+ Tag const BillingItemSequence(0x0040, 0x0296);
+ Tag const TotalTimeOfFluoroscopy(0x0040, 0x0300);
+ Tag const TotalNumberOfExposures(0x0040, 0x0301);
+ Tag const EntranceDose(0x0040, 0x0302);
+ Tag const ExposedArea(0x0040, 0x0303);
+ Tag const DistanceSourceToEntrance(0x0040, 0x0306);
+ Tag const DistanceSourceToSupport(0x0040, 0x0307);
+ Tag const ExposureDoseSequence(0x0040, 0x030e);
+ Tag const CommentsOnRadiationDose(0x0040, 0x0310);
+ Tag const XRayOutput(0x0040, 0x0312);
+ Tag const HalfValueLayer(0x0040, 0x0314);
+ Tag const OrganDose(0x0040, 0x0316);
+ Tag const OrganExposed(0x0040, 0x0318);
+ Tag const BillingProcedureStepSequence(0x0040, 0x0320);
+ Tag const FilmConsumptionSequence(0x0040, 0x0321);
+ Tag const BillingSuppliesAndDevicesSequence(0x0040, 0x0324);
+ Tag const ReferencedProcedureStepSequence(0x0040, 0x0330);
+ Tag const PerformedSeriesSequence(0x0040, 0x0340);
+ Tag const CommentsOnTheScheduledProcedureStep(0x0040, 0x0400);
+ Tag const ProtocolContextSequence(0x0040, 0x0440);
+ Tag const ContentItemModifierSequence(0x0040, 0x0441);
+ Tag const ScheduledSpecimenSequence(0x0040, 0x0500);
+ Tag const SpecimenAccessionNumber(0x0040, 0x050a);
+ Tag const ContainerIdentifier(0x0040, 0x0512);
+ Tag const IssuerOfTheContainerIdentifierSequence(0x0040, 0x0513);
+ Tag const AlternateContainerIdentifierSequence(0x0040, 0x0515);
+ Tag const ContainerTypeCodeSequence(0x0040, 0x0518);
+ Tag const ContainerDescription(0x0040, 0x051a);
+ Tag const ContainerComponentSequence(0x0040, 0x0520);
+ Tag const SpecimenSequence(0x0040, 0x0550);
+ Tag const SpecimenIdentifier(0x0040, 0x0551);
+ Tag const SpecimenDescriptionSequenceTrial(0x0040, 0x0552);
+ Tag const SpecimenDescriptionTrial(0x0040, 0x0553);
+ Tag const SpecimenUID(0x0040, 0x0554);
+ Tag const AcquisitionContextSequence(0x0040, 0x0555);
+ Tag const AcquisitionContextDescription(0x0040, 0x0556);
+ Tag const SpecimenTypeCodeSequence(0x0040, 0x059a);
+ Tag const SpecimenDescriptionSequence(0x0040, 0x0560);
+ Tag const IssuerOfTheSpecimenIdentifierSequence(0x0040, 0x0562);
+ Tag const SpecimenShortDescription(0x0040, 0x0600);
+ Tag const SpecimenDetailedDescription(0x0040, 0x0602);
+ Tag const SpecimenPreparationSequence(0x0040, 0x0610);
+ Tag const SpecimenPreparationStepContentItemSequence(0x0040, 0x0612);
+ Tag const SpecimenLocalizationContentItemSequence(0x0040, 0x0620);
+ Tag const SlideIdentifier(0x0040, 0x06fa);
+ Tag const ImageCenterPointCoordinatesSequence(0x0040, 0x071a);
+ Tag const XOffsetInSlideCoordinateSystem(0x0040, 0x072a);
+ Tag const YOffsetInSlideCoordinateSystem(0x0040, 0x073a);
+ Tag const ZOffsetInSlideCoordinateSystem(0x0040, 0x074a);
+ Tag const PixelSpacingSequence(0x0040, 0x08d8);
+ Tag const CoordinateSystemAxisCodeSequence(0x0040, 0x08da);
+ Tag const MeasurementUnitsCodeSequence(0x0040, 0x08ea);
+ Tag const VitalStainCodeSequenceTrial(0x0040, 0x09f8);
+ Tag const RequestedProcedureID(0x0040, 0x1001);
+ Tag const ReasonForTheRequestedProcedure(0x0040, 0x1002);
+ Tag const RequestedProcedurePriority(0x0040, 0x1003);
+ Tag const PatientTransportArrangements(0x0040, 0x1004);
+ Tag const RequestedProcedureLocation(0x0040, 0x1005);
+ Tag const PlacerOrderNumberProcedure(0x0040, 0x1006);
+ Tag const FillerOrderNumberProcedure(0x0040, 0x1007);
+ Tag const ConfidentialityCode(0x0040, 0x1008);
+ Tag const ReportingPriority(0x0040, 0x1009);
+ Tag const ReasonForRequestedProcedureCodeSequence(0x0040, 0x100a);
+ Tag const NamesOfIntendedRecipientsOfResults(0x0040, 0x1010);
+ Tag const IntendedRecipientsOfResultsIdentificationSequence(0x0040, 0x1011);
+ Tag const ReasonForPerformedProcedureCodeSequence(0x0040, 0x1012);
+ Tag const RequestedProcedureDescriptionTrial(0x0040, 0x1060);
+ Tag const PersonIdentificationCodeSequence(0x0040, 0x1101);
+ Tag const PersonAddress(0x0040, 0x1102);
+ Tag const PersonTelephoneNumbers(0x0040, 0x1103);
+ Tag const RequestedProcedureComments(0x0040, 0x1400);
+ Tag const ReasonForTheImagingServiceRequest(0x0040, 0x2001);
+ Tag const IssueDateOfImagingServiceRequest(0x0040, 0x2004);
+ Tag const IssueTimeOfImagingServiceRequest(0x0040, 0x2005);
+ Tag const PlacerOrderNumberImagingServiceRequestRetired(0x0040, 0x2006);
+ Tag const FillerOrderNumberImagingServiceRequestRetired(0x0040, 0x2007);
+ Tag const OrderEnteredBy(0x0040, 0x2008);
+ Tag const OrderEntererLocation(0x0040, 0x2009);
+ Tag const OrderCallbackPhoneNumber(0x0040, 0x2010);
+ Tag const PlacerOrderNumberImagingServiceRequest(0x0040, 0x2016);
+ Tag const FillerOrderNumberImagingServiceRequest(0x0040, 0x2017);
+ Tag const ImagingServiceRequestComments(0x0040, 0x2400);
+ Tag const ConfidentialityConstraintOnPatientDataDescription(0x0040, 0x3001);
+ Tag const GeneralPurposeScheduledProcedureStepStatus(0x0040, 0x4001);
+ Tag const GeneralPurposePerformedProcedureStepStatus(0x0040, 0x4002);
+ Tag const GeneralPurposeScheduledProcedureStepPriority(0x0040, 0x4003);
+ Tag const ScheduledProcessingApplicationsCodeSequence(0x0040, 0x4004);
+ Tag const ScheduledProcedureStepStartDateTime(0x0040, 0x4005);
+ Tag const MultipleCopiesFlag(0x0040, 0x4006);
+ Tag const PerformedProcessingApplicationsCodeSequence(0x0040, 0x4007);
+ Tag const HumanPerformerCodeSequence(0x0040, 0x4009);
+ Tag const ScheduledProcedureStepModificationDateTime(0x0040, 0x4010);
+ Tag const ExpectedCompletionDateTime(0x0040, 0x4011);
+ Tag const ResultingGeneralPurposePerformedProcedureStepsSequence(0x0040, 0x4015);
+ Tag const ReferencedGeneralPurposeScheduledProcedureStepSequence(0x0040, 0x4016);
+ Tag const ScheduledWorkitemCodeSequence(0x0040, 0x4018);
+ Tag const PerformedWorkitemCodeSequence(0x0040, 0x4019);
+ Tag const InputAvailabilityFlag(0x0040, 0x4020);
+ Tag const InputInformationSequence(0x0040, 0x4021);
+ Tag const RelevantInformationSequence(0x0040, 0x4022);
+ Tag const ReferencedGeneralPurposeScheduledProcedureStepTransactionUID(0x0040, 0x4023);
+ Tag const ScheduledStationNameCodeSequence(0x0040, 0x4025);
+ Tag const ScheduledStationClassCodeSequence(0x0040, 0x4026);
+ Tag const ScheduledStationGeographicLocationCodeSequence(0x0040, 0x4027);
+ Tag const PerformedStationNameCodeSequence(0x0040, 0x4028);
+ Tag const PerformedStationClassCodeSequence(0x0040, 0x4029);
+ Tag const PerformedStationGeographicLocationCodeSequence(0x0040, 0x4030);
+ Tag const RequestedSubsequentWorkitemCodeSequence(0x0040, 0x4031);
+ Tag const NonDICOMOutputCodeSequence(0x0040, 0x4032);
+ Tag const OutputInformationSequence(0x0040, 0x4033);
+ Tag const ScheduledHumanPerformersSequence(0x0040, 0x4034);
+ Tag const ActualHumanPerformersSequence(0x0040, 0x4035);
+ Tag const HumanPerformerOrganization(0x0040, 0x4036);
+ Tag const HumanPerformerName(0x0040, 0x4037);
+ Tag const RawDataHandling(0x0040, 0x4040);
+ Tag const InputReadinessState(0x0040, 0x4041);
+ Tag const PerformedProcedureStepStartDateTime(0x0040, 0x4050);
+ Tag const PerformedProcedureStepEndDateTime(0x0040, 0x4051);
+ Tag const ProcedureStepCancellationDateTime(0x0040, 0x4052);
+ Tag const EntranceDoseInmGy(0x0040, 0x8302);
+ Tag const ParametricMapFrameTypeSequence(0x0040, 0x9092);
+ Tag const ReferencedImageRealWorldValueMappingSequence(0x0040, 0x9094);
+ Tag const RealWorldValueMappingSequence(0x0040, 0x9096);
+ Tag const PixelValueMappingCodeSequence(0x0040, 0x9098);
+ Tag const LUTLabel(0x0040, 0x9210);
+ Tag const RealWorldValueLastValueMapped(0x0040, 0x9211);
+ Tag const RealWorldValueLUTData(0x0040, 0x9212);
+ Tag const RealWorldValueFirstValueMapped(0x0040, 0x9216);
+ Tag const QuantityDefinitionSequence(0x0040, 0x9220);
+ Tag const RealWorldValueIntercept(0x0040, 0x9224);
+ Tag const RealWorldValueSlope(0x0040, 0x9225);
+ Tag const FindingsFlagTrial(0x0040, 0xa007);
+ Tag const RelationshipType(0x0040, 0xa010);
+ Tag const FindingsSequenceTrial(0x0040, 0xa020);
+ Tag const FindingsGroupUIDTrial(0x0040, 0xa021);
+ Tag const ReferencedFindingsGroupUIDTrial(0x0040, 0xa022);
+ Tag const FindingsGroupRecordingDateTrial(0x0040, 0xa023);
+ Tag const FindingsGroupRecordingTimeTrial(0x0040, 0xa024);
+ Tag const FindingsSourceCategoryCodeSequenceTrial(0x0040, 0xa026);
+ Tag const VerifyingOrganization(0x0040, 0xa027);
+ Tag const DocumentingOrganizationIdentifierCodeSequenceTrial(0x0040, 0xa028);
+ Tag const VerificationDateTime(0x0040, 0xa030);
+ Tag const ObservationDateTime(0x0040, 0xa032);
+ Tag const ValueType(0x0040, 0xa040);
+ Tag const ConceptNameCodeSequence(0x0040, 0xa043);
+ Tag const MeasurementPrecisionDescriptionTrial(0x0040, 0xa047);
+ Tag const ContinuityOfContent(0x0040, 0xa050);
+ Tag const UrgencyOrPriorityAlertsTrial(0x0040, 0xa057);
+ Tag const SequencingIndicatorTrial(0x0040, 0xa060);
+ Tag const DocumentIdentifierCodeSequenceTrial(0x0040, 0xa066);
+ Tag const DocumentAuthorTrial(0x0040, 0xa067);
+ Tag const DocumentAuthorIdentifierCodeSequenceTrial(0x0040, 0xa068);
+ Tag const IdentifierCodeSequenceTrial(0x0040, 0xa070);
+ Tag const VerifyingObserverSequence(0x0040, 0xa073);
+ Tag const ObjectBinaryIdentifierTrial(0x0040, 0xa074);
+ Tag const VerifyingObserverName(0x0040, 0xa075);
+ Tag const DocumentingObserverIdentifierCodeSequenceTrial(0x0040, 0xa076);
+ Tag const AuthorObserverSequence(0x0040, 0xa078);
+ Tag const ParticipantSequence(0x0040, 0xa07a);
+ Tag const CustodialOrganizationSequence(0x0040, 0xa07c);
+ Tag const ParticipationType(0x0040, 0xa080);
+ Tag const ParticipationDateTime(0x0040, 0xa082);
+ Tag const ObserverType(0x0040, 0xa084);
+ Tag const ProcedureIdentifierCodeSequenceTrial(0x0040, 0xa085);
+ Tag const VerifyingObserverIdentificationCodeSequence(0x0040, 0xa088);
+ Tag const ObjectDirectoryBinaryIdentifierTrial(0x0040, 0xa089);
+ Tag const EquivalentCDADocumentSequence(0x0040, 0xa090);
+ Tag const ReferencedWaveformChannels(0x0040, 0xa0b0);
+ Tag const DateOfDocumentOrVerbalTransactionTrial(0x0040, 0xa110);
+ Tag const TimeOfDocumentCreationOrVerbalTransactionTrial(0x0040, 0xa112);
+ Tag const DateTime(0x0040, 0xa120);
+ Tag const Date(0x0040, 0xa121);
+ Tag const Time(0x0040, 0xa122);
+ Tag const PersonName(0x0040, 0xa123);
+ Tag const UID(0x0040, 0xa124);
+ Tag const ReportStatusIDTrial(0x0040, 0xa125);
+ Tag const TemporalRangeType(0x0040, 0xa130);
+ Tag const ReferencedSamplePositions(0x0040, 0xa132);
+ Tag const ReferencedFrameNumbers(0x0040, 0xa136);
+ Tag const ReferencedTimeOffsets(0x0040, 0xa138);
+ Tag const ReferencedDateTime(0x0040, 0xa13a);
+ Tag const TextValue(0x0040, 0xa160);
+ Tag const FloatingPointValue(0x0040, 0xa161);
+ Tag const RationalNumeratorValue(0x0040, 0xa162);
+ Tag const RationalDenominatorValue(0x0040, 0xa163);
+ Tag const ObservationCategoryCodeSequenceTrial(0x0040, 0xa167);
+ Tag const ConceptCodeSequence(0x0040, 0xa168);
+ Tag const BibliographicCitationTrial(0x0040, 0xa16a);
+ Tag const PurposeOfReferenceCodeSequence(0x0040, 0xa170);
+ Tag const ObservationUID(0x0040, 0xa171);
+ Tag const ReferencedObservationUIDTrial(0x0040, 0xa172);
+ Tag const ReferencedObservationClassTrial(0x0040, 0xa173);
+ Tag const ReferencedObjectObservationClassTrial(0x0040, 0xa174);
+ Tag const AnnotationGroupNumber(0x0040, 0xa180);
+ Tag const ObservationDateTrial(0x0040, 0xa192);
+ Tag const ObservationTimeTrial(0x0040, 0xa193);
+ Tag const MeasurementAutomationTrial(0x0040, 0xa194);
+ Tag const ModifierCodeSequence(0x0040, 0xa195);
+ Tag const IdentificationDescriptionTrial(0x0040, 0xa224);
+ Tag const CoordinatesSetGeometricTypeTrial(0x0040, 0xa290);
+ Tag const AlgorithmCodeSequenceTrial(0x0040, 0xa296);
+ Tag const AlgorithmDescriptionTrial(0x0040, 0xa297);
+ Tag const PixelCoordinatesSetTrial(0x0040, 0xa29a);
+ Tag const MeasuredValueSequence(0x0040, 0xa300);
+ Tag const NumericValueQualifierCodeSequence(0x0040, 0xa301);
+ Tag const CurrentObserverTrial(0x0040, 0xa307);
+ Tag const NumericValue(0x0040, 0xa30a);
+ Tag const ReferencedAccessionSequenceTrial(0x0040, 0xa313);
+ Tag const ReportStatusCommentTrial(0x0040, 0xa33a);
+ Tag const ProcedureContextSequenceTrial(0x0040, 0xa340);
+ Tag const VerbalSourceTrial(0x0040, 0xa352);
+ Tag const AddressTrial(0x0040, 0xa353);
+ Tag const TelephoneNumberTrial(0x0040, 0xa354);
+ Tag const VerbalSourceIdentifierCodeSequenceTrial(0x0040, 0xa358);
+ Tag const PredecessorDocumentsSequence(0x0040, 0xa360);
+ Tag const ReferencedRequestSequence(0x0040, 0xa370);
+ Tag const PerformedProcedureCodeSequence(0x0040, 0xa372);
+ Tag const CurrentRequestedProcedureEvidenceSequence(0x0040, 0xa375);
+ Tag const ReportDetailSequenceTrial(0x0040, 0xa380);
+ Tag const PertinentOtherEvidenceSequence(0x0040, 0xa385);
+ Tag const HL7StructuredDocumentReferenceSequence(0x0040, 0xa390);
+ Tag const ObservationSubjectUIDTrial(0x0040, 0xa402);
+ Tag const ObservationSubjectClassTrial(0x0040, 0xa403);
+ Tag const ObservationSubjectTypeCodeSequenceTrial(0x0040, 0xa404);
+ Tag const CompletionFlag(0x0040, 0xa491);
+ Tag const CompletionFlagDescription(0x0040, 0xa492);
+ Tag const VerificationFlag(0x0040, 0xa493);
+ Tag const ArchiveRequested(0x0040, 0xa494);
+ Tag const PreliminaryFlag(0x0040, 0xa496);
+ Tag const ContentTemplateSequence(0x0040, 0xa504);
+ Tag const IdenticalDocumentsSequence(0x0040, 0xa525);
+ Tag const ObservationSubjectContextFlagTrial(0x0040, 0xa600);
+ Tag const ObserverContextFlagTrial(0x0040, 0xa601);
+ Tag const ProcedureContextFlagTrial(0x0040, 0xa603);
+ Tag const ContentSequence(0x0040, 0xa730);
+ Tag const RelationshipSequenceTrial(0x0040, 0xa731);
+ Tag const RelationshipTypeCodeSequenceTrial(0x0040, 0xa732);
+ Tag const LanguageCodeSequenceTrial(0x0040, 0xa744);
+ Tag const UniformResourceLocatorTrial(0x0040, 0xa992);
+ Tag const WaveformAnnotationSequence(0x0040, 0xb020);
+ Tag const TemplateIdentifier(0x0040, 0xdb00);
+ Tag const TemplateVersion(0x0040, 0xdb06);
+ Tag const TemplateLocalVersion(0x0040, 0xdb07);
+ Tag const TemplateExtensionFlag(0x0040, 0xdb0b);
+ Tag const TemplateExtensionOrganizationUID(0x0040, 0xdb0c);
+ Tag const TemplateExtensionCreatorUID(0x0040, 0xdb0d);
+ Tag const ReferencedContentItemIdentifier(0x0040, 0xdb73);
+ Tag const HL7InstanceIdentifier(0x0040, 0xe001);
+ Tag const HL7DocumentEffectiveTime(0x0040, 0xe004);
+ Tag const HL7DocumentTypeCodeSequence(0x0040, 0xe006);
+ Tag const DocumentClassCodeSequence(0x0040, 0xe008);
+ Tag const RetrieveURI(0x0040, 0xe010);
+ Tag const RetrieveLocationUID(0x0040, 0xe011);
+ Tag const TypeOfInstances(0x0040, 0xe020);
+ Tag const DICOMRetrievalSequence(0x0040, 0xe021);
+ Tag const DICOMMediaRetrievalSequence(0x0040, 0xe022);
+ Tag const WADORetrievalSequence(0x0040, 0xe023);
+ Tag const XDSRetrievalSequence(0x0040, 0xe024);
+ Tag const WADORSRetrievalSequence(0x0040, 0xe025);
+ Tag const RepositoryUniqueID(0x0040, 0xe030);
+ Tag const HomeCommunityID(0x0040, 0xe031);
+ Tag const DocumentTitle(0x0042, 0x0010);
+ Tag const EncapsulatedDocument(0x0042, 0x0011);
+ Tag const MIMETypeOfEncapsulatedDocument(0x0042, 0x0012);
+ Tag const SourceInstanceSequence(0x0042, 0x0013);
+ Tag const ListOfMIMETypes(0x0042, 0x0014);
+ Tag const ProductPackageIdentifier(0x0044, 0x0001);
+ Tag const SubstanceAdministrationApproval(0x0044, 0x0002);
+ Tag const ApprovalStatusFurtherDescription(0x0044, 0x0003);
+ Tag const ApprovalStatusDateTime(0x0044, 0x0004);
+ Tag const ProductTypeCodeSequence(0x0044, 0x0007);
+ Tag const ProductName(0x0044, 0x0008);
+ Tag const ProductDescription(0x0044, 0x0009);
+ Tag const ProductLotIdentifier(0x0044, 0x000a);
+ Tag const ProductExpirationDateTime(0x0044, 0x000b);
+ Tag const SubstanceAdministrationDateTime(0x0044, 0x0010);
+ Tag const SubstanceAdministrationNotes(0x0044, 0x0011);
+ Tag const SubstanceAdministrationDeviceID(0x0044, 0x0012);
+ Tag const ProductParameterSequence(0x0044, 0x0013);
+ Tag const SubstanceAdministrationParameterSequence(0x0044, 0x0019);
+ Tag const LensDescription(0x0046, 0x0012);
+ Tag const RightLensSequence(0x0046, 0x0014);
+ Tag const LeftLensSequence(0x0046, 0x0015);
+ Tag const UnspecifiedLateralityLensSequence(0x0046, 0x0016);
+ Tag const CylinderSequence(0x0046, 0x0018);
+ Tag const PrismSequence(0x0046, 0x0028);
+ Tag const HorizontalPrismPower(0x0046, 0x0030);
+ Tag const HorizontalPrismBase(0x0046, 0x0032);
+ Tag const VerticalPrismPower(0x0046, 0x0034);
+ Tag const VerticalPrismBase(0x0046, 0x0036);
+ Tag const LensSegmentType(0x0046, 0x0038);
+ Tag const OpticalTransmittance(0x0046, 0x0040);
+ Tag const ChannelWidth(0x0046, 0x0042);
+ Tag const PupilSize(0x0046, 0x0044);
+ Tag const CornealSize(0x0046, 0x0046);
+ Tag const AutorefractionRightEyeSequence(0x0046, 0x0050);
+ Tag const AutorefractionLeftEyeSequence(0x0046, 0x0052);
+ Tag const DistancePupillaryDistance(0x0046, 0x0060);
+ Tag const NearPupillaryDistance(0x0046, 0x0062);
+ Tag const IntermediatePupillaryDistance(0x0046, 0x0063);
+ Tag const OtherPupillaryDistance(0x0046, 0x0064);
+ Tag const KeratometryRightEyeSequence(0x0046, 0x0070);
+ Tag const KeratometryLeftEyeSequence(0x0046, 0x0071);
+ Tag const SteepKeratometricAxisSequence(0x0046, 0x0074);
+ Tag const RadiusOfCurvature(0x0046, 0x0075);
+ Tag const KeratometricPower(0x0046, 0x0076);
+ Tag const KeratometricAxis(0x0046, 0x0077);
+ Tag const FlatKeratometricAxisSequence(0x0046, 0x0080);
+ Tag const BackgroundColor(0x0046, 0x0092);
+ Tag const Optotype(0x0046, 0x0094);
+ Tag const OptotypePresentation(0x0046, 0x0095);
+ Tag const SubjectiveRefractionRightEyeSequence(0x0046, 0x0097);
+ Tag const SubjectiveRefractionLeftEyeSequence(0x0046, 0x0098);
+ Tag const AddNearSequence(0x0046, 0x0100);
+ Tag const AddIntermediateSequence(0x0046, 0x0101);
+ Tag const AddOtherSequence(0x0046, 0x0102);
+ Tag const AddPower(0x0046, 0x0104);
+ Tag const ViewingDistance(0x0046, 0x0106);
+ Tag const VisualAcuityTypeCodeSequence(0x0046, 0x0121);
+ Tag const VisualAcuityRightEyeSequence(0x0046, 0x0122);
+ Tag const VisualAcuityLeftEyeSequence(0x0046, 0x0123);
+ Tag const VisualAcuityBothEyesOpenSequence(0x0046, 0x0124);
+ Tag const ViewingDistanceType(0x0046, 0x0125);
+ Tag const VisualAcuityModifiers(0x0046, 0x0135);
+ Tag const DecimalVisualAcuity(0x0046, 0x0137);
+ Tag const OptotypeDetailedDefinition(0x0046, 0x0139);
+ Tag const ReferencedRefractiveMeasurementsSequence(0x0046, 0x0145);
+ Tag const SpherePower(0x0046, 0x0146);
+ Tag const CylinderPower(0x0046, 0x0147);
+ Tag const CornealTopographySurface(0x0046, 0x0201);
+ Tag const CornealVertexLocation(0x0046, 0x0202);
+ Tag const PupilCentroidXCoordinate(0x0046, 0x0203);
+ Tag const PupilCentroidYCoordinate(0x0046, 0x0204);
+ Tag const EquivalentPupilRadius(0x0046, 0x0205);
+ Tag const CornealTopographyMapTypeCodeSequence(0x0046, 0x0207);
+ Tag const VerticesOfTheOutlineOfPupil(0x0046, 0x0208);
+ Tag const CornealTopographyMappingNormalsSequence(0x0046, 0x0210);
+ Tag const MaximumCornealCurvatureSequence(0x0046, 0x0211);
+ Tag const MaximumCornealCurvature(0x0046, 0x0212);
+ Tag const MaximumCornealCurvatureLocation(0x0046, 0x0213);
+ Tag const MinimumKeratometricSequence(0x0046, 0x0215);
+ Tag const SimulatedKeratometricCylinderSequence(0x0046, 0x0218);
+ Tag const AverageCornealPower(0x0046, 0x0220);
+ Tag const CornealISValue(0x0046, 0x0224);
+ Tag const AnalyzedArea(0x0046, 0x0227);
+ Tag const SurfaceRegularityIndex(0x0046, 0x0230);
+ Tag const SurfaceAsymmetryIndex(0x0046, 0x0232);
+ Tag const CornealEccentricityIndex(0x0046, 0x0234);
+ Tag const KeratoconusPredictionIndex(0x0046, 0x0236);
+ Tag const DecimalPotentialVisualAcuity(0x0046, 0x0238);
+ Tag const CornealTopographyMapQualityEvaluation(0x0046, 0x0242);
+ Tag const SourceImageCornealProcessedDataSequence(0x0046, 0x0244);
+ Tag const CornealPointLocation(0x0046, 0x0247);
+ Tag const CornealPointEstimated(0x0046, 0x0248);
+ Tag const AxialPower(0x0046, 0x0249);
+ Tag const TangentialPower(0x0046, 0x0250);
+ Tag const RefractivePower(0x0046, 0x0251);
+ Tag const RelativeElevation(0x0046, 0x0252);
+ Tag const CornealWavefront(0x0046, 0x0253);
+ Tag const ImagedVolumeWidth(0x0048, 0x0001);
+ Tag const ImagedVolumeHeight(0x0048, 0x0002);
+ Tag const ImagedVolumeDepth(0x0048, 0x0003);
+ Tag const TotalPixelMatrixColumns(0x0048, 0x0006);
+ Tag const TotalPixelMatrixRows(0x0048, 0x0007);
+ Tag const TotalPixelMatrixOriginSequence(0x0048, 0x0008);
+ Tag const SpecimenLabelInImage(0x0048, 0x0010);
+ Tag const FocusMethod(0x0048, 0x0011);
+ Tag const ExtendedDepthOfField(0x0048, 0x0012);
+ Tag const NumberOfFocalPlanes(0x0048, 0x0013);
+ Tag const DistanceBetweenFocalPlanes(0x0048, 0x0014);
+ Tag const RecommendedAbsentPixelCIELabValue(0x0048, 0x0015);
+ Tag const IlluminatorTypeCodeSequence(0x0048, 0x0100);
+ Tag const ImageOrientationSlide(0x0048, 0x0102);
+ Tag const OpticalPathSequence(0x0048, 0x0105);
+ Tag const OpticalPathIdentifier(0x0048, 0x0106);
+ Tag const OpticalPathDescription(0x0048, 0x0107);
+ Tag const IlluminationColorCodeSequence(0x0048, 0x0108);
+ Tag const SpecimenReferenceSequence(0x0048, 0x0110);
+ Tag const CondenserLensPower(0x0048, 0x0111);
+ Tag const ObjectiveLensPower(0x0048, 0x0112);
+ Tag const ObjectiveLensNumericalAperture(0x0048, 0x0113);
+ Tag const PaletteColorLookupTableSequence(0x0048, 0x0120);
+ Tag const ReferencedImageNavigationSequence(0x0048, 0x0200);
+ Tag const TopLeftHandCornerOfLocalizerArea(0x0048, 0x0201);
+ Tag const BottomRightHandCornerOfLocalizerArea(0x0048, 0x0202);
+ Tag const OpticalPathIdentificationSequence(0x0048, 0x0207);
+ Tag const PlanePositionSlideSequence(0x0048, 0x021a);
+ Tag const ColumnPositionInTotalImagePixelMatrix(0x0048, 0x021e);
+ Tag const RowPositionInTotalImagePixelMatrix(0x0048, 0x021f);
+ Tag const PixelOriginInterpretation(0x0048, 0x0301);
+ Tag const CalibrationImage(0x0050, 0x0004);
+ Tag const DeviceSequence(0x0050, 0x0010);
+ Tag const ContainerComponentTypeCodeSequence(0x0050, 0x0012);
+ Tag const ContainerComponentThickness(0x0050, 0x0013);
+ Tag const DeviceLength(0x0050, 0x0014);
+ Tag const ContainerComponentWidth(0x0050, 0x0015);
+ Tag const DeviceDiameter(0x0050, 0x0016);
+ Tag const DeviceDiameterUnits(0x0050, 0x0017);
+ Tag const DeviceVolume(0x0050, 0x0018);
+ Tag const InterMarkerDistance(0x0050, 0x0019);
+ Tag const ContainerComponentMaterial(0x0050, 0x001a);
+ Tag const ContainerComponentID(0x0050, 0x001b);
+ Tag const ContainerComponentLength(0x0050, 0x001c);
+ Tag const ContainerComponentDiameter(0x0050, 0x001d);
+ Tag const ContainerComponentDescription(0x0050, 0x001e);
+ Tag const DeviceDescription(0x0050, 0x0020);
+ Tag const ContrastBolusIngredientPercentByVolume(0x0052, 0x0001);
+ Tag const OCTFocalDistance(0x0052, 0x0002);
+ Tag const BeamSpotSize(0x0052, 0x0003);
+ Tag const EffectiveRefractiveIndex(0x0052, 0x0004);
+ Tag const OCTAcquisitionDomain(0x0052, 0x0006);
+ Tag const OCTOpticalCenterWavelength(0x0052, 0x0007);
+ Tag const AxialResolution(0x0052, 0x0008);
+ Tag const RangingDepth(0x0052, 0x0009);
+ Tag const ALineRate(0x0052, 0x0011);
+ Tag const ALinesPerFrame(0x0052, 0x0012);
+ Tag const CatheterRotationalRate(0x0052, 0x0013);
+ Tag const ALinePixelSpacing(0x0052, 0x0014);
+ Tag const ModeOfPercutaneousAccessSequence(0x0052, 0x0016);
+ Tag const IntravascularOCTFrameTypeSequence(0x0052, 0x0025);
+ Tag const OCTZOffsetApplied(0x0052, 0x0026);
+ Tag const IntravascularFrameContentSequence(0x0052, 0x0027);
+ Tag const IntravascularLongitudinalDistance(0x0052, 0x0028);
+ Tag const IntravascularOCTFrameContentSequence(0x0052, 0x0029);
+ Tag const OCTZOffsetCorrection(0x0052, 0x0030);
+ Tag const CatheterDirectionOfRotation(0x0052, 0x0031);
+ Tag const SeamLineLocation(0x0052, 0x0033);
+ Tag const FirstALineLocation(0x0052, 0x0034);
+ Tag const SeamLineIndex(0x0052, 0x0036);
+ Tag const NumberOfPaddedALines(0x0052, 0x0038);
+ Tag const InterpolationType(0x0052, 0x0039);
+ Tag const RefractiveIndexApplied(0x0052, 0x003a);
+ Tag const EnergyWindowVector(0x0054, 0x0010);
+ Tag const NumberOfEnergyWindows(0x0054, 0x0011);
+ Tag const EnergyWindowInformationSequence(0x0054, 0x0012);
+ Tag const EnergyWindowRangeSequence(0x0054, 0x0013);
+ Tag const EnergyWindowLowerLimit(0x0054, 0x0014);
+ Tag const EnergyWindowUpperLimit(0x0054, 0x0015);
+ Tag const RadiopharmaceuticalInformationSequence(0x0054, 0x0016);
+ Tag const ResidualSyringeCounts(0x0054, 0x0017);
+ Tag const EnergyWindowName(0x0054, 0x0018);
+ Tag const DetectorVector(0x0054, 0x0020);
+ Tag const NumberOfDetectors(0x0054, 0x0021);
+ Tag const DetectorInformationSequence(0x0054, 0x0022);
+ Tag const PhaseVector(0x0054, 0x0030);
+ Tag const NumberOfPhases(0x0054, 0x0031);
+ Tag const PhaseInformationSequence(0x0054, 0x0032);
+ Tag const NumberOfFramesInPhase(0x0054, 0x0033);
+ Tag const PhaseDelay(0x0054, 0x0036);
+ Tag const PauseBetweenFrames(0x0054, 0x0038);
+ Tag const PhaseDescription(0x0054, 0x0039);
+ Tag const RotationVector(0x0054, 0x0050);
+ Tag const NumberOfRotations(0x0054, 0x0051);
+ Tag const RotationInformationSequence(0x0054, 0x0052);
+ Tag const NumberOfFramesInRotation(0x0054, 0x0053);
+ Tag const RRIntervalVector(0x0054, 0x0060);
+ Tag const NumberOfRRIntervals(0x0054, 0x0061);
+ Tag const GatedInformationSequence(0x0054, 0x0062);
+ Tag const DataInformationSequence(0x0054, 0x0063);
+ Tag const TimeSlotVector(0x0054, 0x0070);
+ Tag const NumberOfTimeSlots(0x0054, 0x0071);
+ Tag const TimeSlotInformationSequence(0x0054, 0x0072);
+ Tag const TimeSlotTime(0x0054, 0x0073);
+ Tag const SliceVector(0x0054, 0x0080);
+ Tag const NumberOfSlices(0x0054, 0x0081);
+ Tag const AngularViewVector(0x0054, 0x0090);
+ Tag const TimeSliceVector(0x0054, 0x0100);
+ Tag const NumberOfTimeSlices(0x0054, 0x0101);
+ Tag const StartAngle(0x0054, 0x0200);
+ Tag const TypeOfDetectorMotion(0x0054, 0x0202);
+ Tag const TriggerVector(0x0054, 0x0210);
+ Tag const NumberOfTriggersInPhase(0x0054, 0x0211);
+ Tag const ViewCodeSequence(0x0054, 0x0220);
+ Tag const ViewModifierCodeSequence(0x0054, 0x0222);
+ Tag const RadionuclideCodeSequence(0x0054, 0x0300);
+ Tag const AdministrationRouteCodeSequence(0x0054, 0x0302);
+ Tag const RadiopharmaceuticalCodeSequence(0x0054, 0x0304);
+ Tag const CalibrationDataSequence(0x0054, 0x0306);
+ Tag const EnergyWindowNumber(0x0054, 0x0308);
+ Tag const ImageID(0x0054, 0x0400);
+ Tag const PatientOrientationCodeSequence(0x0054, 0x0410);
+ Tag const PatientOrientationModifierCodeSequence(0x0054, 0x0412);
+ Tag const PatientGantryRelationshipCodeSequence(0x0054, 0x0414);
+ Tag const SliceProgressionDirection(0x0054, 0x0500);
+ Tag const ScanProgressionDirection(0x0054, 0x0501);
+ Tag const SeriesType(0x0054, 0x1000);
+ Tag const Units(0x0054, 0x1001);
+ Tag const CountsSource(0x0054, 0x1002);
+ Tag const ReprojectionMethod(0x0054, 0x1004);
+ Tag const SUVType(0x0054, 0x1006);
+ Tag const RandomsCorrectionMethod(0x0054, 0x1100);
+ Tag const AttenuationCorrectionMethod(0x0054, 0x1101);
+ Tag const DecayCorrection(0x0054, 0x1102);
+ Tag const ReconstructionMethod(0x0054, 0x1103);
+ Tag const DetectorLinesOfResponseUsed(0x0054, 0x1104);
+ Tag const ScatterCorrectionMethod(0x0054, 0x1105);
+ Tag const AxialAcceptance(0x0054, 0x1200);
+ Tag const AxialMash(0x0054, 0x1201);
+ Tag const TransverseMash(0x0054, 0x1202);
+ Tag const DetectorElementSize(0x0054, 0x1203);
+ Tag const CoincidenceWindowWidth(0x0054, 0x1210);
+ Tag const SecondaryCountsType(0x0054, 0x1220);
+ Tag const FrameReferenceTime(0x0054, 0x1300);
+ Tag const PrimaryPromptsCountsAccumulated(0x0054, 0x1310);
+ Tag const SecondaryCountsAccumulated(0x0054, 0x1311);
+ Tag const SliceSensitivityFactor(0x0054, 0x1320);
+ Tag const DecayFactor(0x0054, 0x1321);
+ Tag const DoseCalibrationFactor(0x0054, 0x1322);
+ Tag const ScatterFractionFactor(0x0054, 0x1323);
+ Tag const DeadTimeFactor(0x0054, 0x1324);
+ Tag const ImageIndex(0x0054, 0x1330);
+ Tag const CountsIncluded(0x0054, 0x1400);
+ Tag const DeadTimeCorrectionFlag(0x0054, 0x1401);
+ Tag const HistogramSequence(0x0060, 0x3000);
+ Tag const HistogramNumberOfBins(0x0060, 0x3002);
+ Tag const HistogramFirstBinValue(0x0060, 0x3004);
+ Tag const HistogramLastBinValue(0x0060, 0x3006);
+ Tag const HistogramBinWidth(0x0060, 0x3008);
+ Tag const HistogramExplanation(0x0060, 0x3010);
+ Tag const HistogramData(0x0060, 0x3020);
+ Tag const SegmentationType(0x0062, 0x0001);
+ Tag const SegmentSequence(0x0062, 0x0002);
+ Tag const SegmentedPropertyCategoryCodeSequence(0x0062, 0x0003);
+ Tag const SegmentNumber(0x0062, 0x0004);
+ Tag const SegmentLabel(0x0062, 0x0005);
+ Tag const SegmentDescription(0x0062, 0x0006);
+ Tag const SegmentAlgorithmType(0x0062, 0x0008);
+ Tag const SegmentAlgorithmName(0x0062, 0x0009);
+ Tag const SegmentIdentificationSequence(0x0062, 0x000a);
+ Tag const ReferencedSegmentNumber(0x0062, 0x000b);
+ Tag const RecommendedDisplayGrayscaleValue(0x0062, 0x000c);
+ Tag const RecommendedDisplayCIELabValue(0x0062, 0x000d);
+ Tag const MaximumFractionalValue(0x0062, 0x000e);
+ Tag const SegmentedPropertyTypeCodeSequence(0x0062, 0x000f);
+ Tag const SegmentationFractionalType(0x0062, 0x0010);
+ Tag const SegmentedPropertyTypeModifierCodeSequence(0x0062, 0x0011);
+ Tag const UsedSegmentsSequence(0x0062, 0x0012);
+ Tag const DeformableRegistrationSequence(0x0064, 0x0002);
+ Tag const SourceFrameOfReferenceUID(0x0064, 0x0003);
+ Tag const DeformableRegistrationGridSequence(0x0064, 0x0005);
+ Tag const GridDimensions(0x0064, 0x0007);
+ Tag const GridResolution(0x0064, 0x0008);
+ Tag const VectorGridData(0x0064, 0x0009);
+ Tag const PreDeformationMatrixRegistrationSequence(0x0064, 0x000f);
+ Tag const PostDeformationMatrixRegistrationSequence(0x0064, 0x0010);
+ Tag const NumberOfSurfaces(0x0066, 0x0001);
+ Tag const SurfaceSequence(0x0066, 0x0002);
+ Tag const SurfaceNumber(0x0066, 0x0003);
+ Tag const SurfaceComments(0x0066, 0x0004);
+ Tag const SurfaceProcessing(0x0066, 0x0009);
+ Tag const SurfaceProcessingRatio(0x0066, 0x000a);
+ Tag const SurfaceProcessingDescription(0x0066, 0x000b);
+ Tag const RecommendedPresentationOpacity(0x0066, 0x000c);
+ Tag const RecommendedPresentationType(0x0066, 0x000d);
+ Tag const FiniteVolume(0x0066, 0x000e);
+ Tag const Manifold(0x0066, 0x0010);
+ Tag const SurfacePointsSequence(0x0066, 0x0011);
+ Tag const SurfacePointsNormalsSequence(0x0066, 0x0012);
+ Tag const SurfaceMeshPrimitivesSequence(0x0066, 0x0013);
+ Tag const NumberOfSurfacePoints(0x0066, 0x0015);
+ Tag const PointCoordinatesData(0x0066, 0x0016);
+ Tag const PointPositionAccuracy(0x0066, 0x0017);
+ Tag const MeanPointDistance(0x0066, 0x0018);
+ Tag const MaximumPointDistance(0x0066, 0x0019);
+ Tag const PointsBoundingBoxCoordinates(0x0066, 0x001a);
+ Tag const AxisOfRotation(0x0066, 0x001b);
+ Tag const CenterOfRotation(0x0066, 0x001c);
+ Tag const NumberOfVectors(0x0066, 0x001e);
+ Tag const VectorDimensionality(0x0066, 0x001f);
+ Tag const VectorAccuracy(0x0066, 0x0020);
+ Tag const VectorCoordinateData(0x0066, 0x0021);
+ Tag const TrianglePointIndexList(0x0066, 0x0023);
+ Tag const EdgePointIndexList(0x0066, 0x0024);
+ Tag const VertexPointIndexList(0x0066, 0x0025);
+ Tag const TriangleStripSequence(0x0066, 0x0026);
+ Tag const TriangleFanSequence(0x0066, 0x0027);
+ Tag const LineSequence(0x0066, 0x0028);
+ Tag const PrimitivePointIndexList(0x0066, 0x0029);
+ Tag const SurfaceCount(0x0066, 0x002a);
+ Tag const ReferencedSurfaceSequence(0x0066, 0x002b);
+ Tag const ReferencedSurfaceNumber(0x0066, 0x002c);
+ Tag const SegmentSurfaceGenerationAlgorithmIdentificationSequence(0x0066, 0x002d);
+ Tag const SegmentSurfaceSourceInstanceSequence(0x0066, 0x002e);
+ Tag const AlgorithmFamilyCodeSequence(0x0066, 0x002f);
+ Tag const AlgorithmNameCodeSequence(0x0066, 0x0030);
+ Tag const AlgorithmVersion(0x0066, 0x0031);
+ Tag const AlgorithmParameters(0x0066, 0x0032);
+ Tag const FacetSequence(0x0066, 0x0034);
+ Tag const SurfaceProcessingAlgorithmIdentificationSequence(0x0066, 0x0035);
+ Tag const AlgorithmName(0x0066, 0x0036);
+ Tag const RecommendedPointRadius(0x0066, 0x0037);
+ Tag const RecommendedLineThickness(0x0066, 0x0038);
+ Tag const LongPrimitivePointIndexList(0x0066, 0x0040);
+ Tag const LongTrianglePointIndexList(0x0066, 0x0041);
+ Tag const LongEdgePointIndexList(0x0066, 0x0042);
+ Tag const LongVertexPointIndexList(0x0066, 0x0043);
+ Tag const ImplantSize(0x0068, 0x6210);
+ Tag const ImplantTemplateVersion(0x0068, 0x6221);
+ Tag const ReplacedImplantTemplateSequence(0x0068, 0x6222);
+ Tag const ImplantType(0x0068, 0x6223);
+ Tag const DerivationImplantTemplateSequence(0x0068, 0x6224);
+ Tag const OriginalImplantTemplateSequence(0x0068, 0x6225);
+ Tag const EffectiveDateTime(0x0068, 0x6226);
+ Tag const ImplantTargetAnatomySequence(0x0068, 0x6230);
+ Tag const InformationFromManufacturerSequence(0x0068, 0x6260);
+ Tag const NotificationFromManufacturerSequence(0x0068, 0x6265);
+ Tag const InformationIssueDateTime(0x0068, 0x6270);
+ Tag const InformationSummary(0x0068, 0x6280);
+ Tag const ImplantRegulatoryDisapprovalCodeSequence(0x0068, 0x62a0);
+ Tag const OverallTemplateSpatialTolerance(0x0068, 0x62a5);
+ Tag const HPGLDocumentSequence(0x0068, 0x62c0);
+ Tag const HPGLDocumentID(0x0068, 0x62d0);
+ Tag const HPGLDocumentLabel(0x0068, 0x62d5);
+ Tag const ViewOrientationCodeSequence(0x0068, 0x62e0);
+ Tag const ViewOrientationModifier(0x0068, 0x62f0);
+ Tag const HPGLDocumentScaling(0x0068, 0x62f2);
+ Tag const HPGLDocument(0x0068, 0x6300);
+ Tag const HPGLContourPenNumber(0x0068, 0x6310);
+ Tag const HPGLPenSequence(0x0068, 0x6320);
+ Tag const HPGLPenNumber(0x0068, 0x6330);
+ Tag const HPGLPenLabel(0x0068, 0x6340);
+ Tag const HPGLPenDescription(0x0068, 0x6345);
+ Tag const RecommendedRotationPoint(0x0068, 0x6346);
+ Tag const BoundingRectangle(0x0068, 0x6347);
+ Tag const ImplantTemplate3DModelSurfaceNumber(0x0068, 0x6350);
+ Tag const SurfaceModelDescriptionSequence(0x0068, 0x6360);
+ Tag const SurfaceModelLabel(0x0068, 0x6380);
+ Tag const SurfaceModelScalingFactor(0x0068, 0x6390);
+ Tag const MaterialsCodeSequence(0x0068, 0x63a0);
+ Tag const CoatingMaterialsCodeSequence(0x0068, 0x63a4);
+ Tag const ImplantTypeCodeSequence(0x0068, 0x63a8);
+ Tag const FixationMethodCodeSequence(0x0068, 0x63ac);
+ Tag const MatingFeatureSetsSequence(0x0068, 0x63b0);
+ Tag const MatingFeatureSetID(0x0068, 0x63c0);
+ Tag const MatingFeatureSetLabel(0x0068, 0x63d0);
+ Tag const MatingFeatureSequence(0x0068, 0x63e0);
+ Tag const MatingFeatureID(0x0068, 0x63f0);
+ Tag const MatingFeatureDegreeOfFreedomSequence(0x0068, 0x6400);
+ Tag const DegreeOfFreedomID(0x0068, 0x6410);
+ Tag const DegreeOfFreedomType(0x0068, 0x6420);
+ Tag const TwoDMatingFeatureCoordinatesSequence(0x0068, 0x6430);
+ Tag const ReferencedHPGLDocumentID(0x0068, 0x6440);
+ Tag const TwoDMatingPoint(0x0068, 0x6450);
+ Tag const TwoDMatingAxes(0x0068, 0x6460);
+ Tag const TwoDDegreeOfFreedomSequence(0x0068, 0x6470);
+ Tag const ThreeDDegreeOfFreedomAxis(0x0068, 0x6490);
+ Tag const RangeOfFreedom(0x0068, 0x64a0);
+ Tag const ThreeDMatingPoint(0x0068, 0x64c0);
+ Tag const ThreeDMatingAxes(0x0068, 0x64d0);
+ Tag const TwoDDegreeOfFreedomAxis(0x0068, 0x64f0);
+ Tag const PlanningLandmarkPointSequence(0x0068, 0x6500);
+ Tag const PlanningLandmarkLineSequence(0x0068, 0x6510);
+ Tag const PlanningLandmarkPlaneSequence(0x0068, 0x6520);
+ Tag const PlanningLandmarkID(0x0068, 0x6530);
+ Tag const PlanningLandmarkDescription(0x0068, 0x6540);
+ Tag const PlanningLandmarkIdentificationCodeSequence(0x0068, 0x6545);
+ Tag const TwoDPointCoordinatesSequence(0x0068, 0x6550);
+ Tag const TwoDPointCoordinates(0x0068, 0x6560);
+ Tag const ThreeDPointCoordinates(0x0068, 0x6590);
+ Tag const TwoDLineCoordinatesSequence(0x0068, 0x65a0);
+ Tag const TwoDLineCoordinates(0x0068, 0x65b0);
+ Tag const ThreeDLineCoordinates(0x0068, 0x65d0);
+ Tag const TwoDPlaneCoordinatesSequence(0x0068, 0x65e0);
+ Tag const TwoDPlaneIntersection(0x0068, 0x65f0);
+ Tag const ThreeDPlaneOrigin(0x0068, 0x6610);
+ Tag const ThreeDPlaneNormal(0x0068, 0x6620);
+ Tag const GraphicAnnotationSequence(0x0070, 0x0001);
+ Tag const GraphicLayer(0x0070, 0x0002);
+ Tag const BoundingBoxAnnotationUnits(0x0070, 0x0003);
+ Tag const AnchorPointAnnotationUnits(0x0070, 0x0004);
+ Tag const GraphicAnnotationUnits(0x0070, 0x0005);
+ Tag const UnformattedTextValue(0x0070, 0x0006);
+ Tag const TextObjectSequence(0x0070, 0x0008);
+ Tag const GraphicObjectSequence(0x0070, 0x0009);
+ Tag const BoundingBoxTopLeftHandCorner(0x0070, 0x0010);
+ Tag const BoundingBoxBottomRightHandCorner(0x0070, 0x0011);
+ Tag const BoundingBoxTextHorizontalJustification(0x0070, 0x0012);
+ Tag const AnchorPoint(0x0070, 0x0014);
+ Tag const AnchorPointVisibility(0x0070, 0x0015);
+ Tag const GraphicDimensions(0x0070, 0x0020);
+ Tag const NumberOfGraphicPoints(0x0070, 0x0021);
+ Tag const GraphicData(0x0070, 0x0022);
+ Tag const GraphicType(0x0070, 0x0023);
+ Tag const GraphicFilled(0x0070, 0x0024);
+ Tag const ImageRotationRetired(0x0070, 0x0040);
+ Tag const ImageHorizontalFlip(0x0070, 0x0041);
+ Tag const ImageRotation(0x0070, 0x0042);
+ Tag const DisplayedAreaTopLeftHandCornerTrial(0x0070, 0x0050);
+ Tag const DisplayedAreaBottomRightHandCornerTrial(0x0070, 0x0051);
+ Tag const DisplayedAreaTopLeftHandCorner(0x0070, 0x0052);
+ Tag const DisplayedAreaBottomRightHandCorner(0x0070, 0x0053);
+ Tag const DisplayedAreaSelectionSequence(0x0070, 0x005a);
+ Tag const GraphicLayerSequence(0x0070, 0x0060);
+ Tag const GraphicLayerOrder(0x0070, 0x0062);
+ Tag const GraphicLayerRecommendedDisplayGrayscaleValue(0x0070, 0x0066);
+ Tag const GraphicLayerRecommendedDisplayRGBValue(0x0070, 0x0067);
+ Tag const GraphicLayerDescription(0x0070, 0x0068);
+ Tag const ContentLabel(0x0070, 0x0080);
+ Tag const ContentDescription(0x0070, 0x0081);
+ Tag const PresentationCreationDate(0x0070, 0x0082);
+ Tag const PresentationCreationTime(0x0070, 0x0083);
+ Tag const ContentCreatorName(0x0070, 0x0084);
+ Tag const ContentCreatorIdentificationCodeSequence(0x0070, 0x0086);
+ Tag const AlternateContentDescriptionSequence(0x0070, 0x0087);
+ Tag const PresentationSizeMode(0x0070, 0x0100);
+ Tag const PresentationPixelSpacing(0x0070, 0x0101);
+ Tag const PresentationPixelAspectRatio(0x0070, 0x0102);
+ Tag const PresentationPixelMagnificationRatio(0x0070, 0x0103);
+ Tag const GraphicGroupLabel(0x0070, 0x0207);
+ Tag const GraphicGroupDescription(0x0070, 0x0208);
+ Tag const CompoundGraphicSequence(0x0070, 0x0209);
+ Tag const CompoundGraphicInstanceID(0x0070, 0x0226);
+ Tag const FontName(0x0070, 0x0227);
+ Tag const FontNameType(0x0070, 0x0228);
+ Tag const CSSFontName(0x0070, 0x0229);
+ Tag const RotationAngle(0x0070, 0x0230);
+ Tag const TextStyleSequence(0x0070, 0x0231);
+ Tag const LineStyleSequence(0x0070, 0x0232);
+ Tag const FillStyleSequence(0x0070, 0x0233);
+ Tag const GraphicGroupSequence(0x0070, 0x0234);
+ Tag const TextColorCIELabValue(0x0070, 0x0241);
+ Tag const HorizontalAlignment(0x0070, 0x0242);
+ Tag const VerticalAlignment(0x0070, 0x0243);
+ Tag const ShadowStyle(0x0070, 0x0244);
+ Tag const ShadowOffsetX(0x0070, 0x0245);
+ Tag const ShadowOffsetY(0x0070, 0x0246);
+ Tag const ShadowColorCIELabValue(0x0070, 0x0247);
+ Tag const Underlined(0x0070, 0x0248);
+ Tag const Bold(0x0070, 0x0249);
+ Tag const Italic(0x0070, 0x0250);
+ Tag const PatternOnColorCIELabValue(0x0070, 0x0251);
+ Tag const PatternOffColorCIELabValue(0x0070, 0x0252);
+ Tag const LineThickness(0x0070, 0x0253);
+ Tag const LineDashingStyle(0x0070, 0x0254);
+ Tag const LinePattern(0x0070, 0x0255);
+ Tag const FillPattern(0x0070, 0x0256);
+ Tag const FillMode(0x0070, 0x0257);
+ Tag const ShadowOpacity(0x0070, 0x0258);
+ Tag const GapLength(0x0070, 0x0261);
+ Tag const DiameterOfVisibility(0x0070, 0x0262);
+ Tag const RotationPoint(0x0070, 0x0273);
+ Tag const TickAlignment(0x0070, 0x0274);
+ Tag const ShowTickLabel(0x0070, 0x0278);
+ Tag const TickLabelAlignment(0x0070, 0x0279);
+ Tag const CompoundGraphicUnits(0x0070, 0x0282);
+ Tag const PatternOnOpacity(0x0070, 0x0284);
+ Tag const PatternOffOpacity(0x0070, 0x0285);
+ Tag const MajorTicksSequence(0x0070, 0x0287);
+ Tag const TickPosition(0x0070, 0x0288);
+ Tag const TickLabel(0x0070, 0x0289);
+ Tag const CompoundGraphicType(0x0070, 0x0294);
+ Tag const GraphicGroupID(0x0070, 0x0295);
+ Tag const ShapeType(0x0070, 0x0306);
+ Tag const RegistrationSequence(0x0070, 0x0308);
+ Tag const MatrixRegistrationSequence(0x0070, 0x0309);
+ Tag const MatrixSequence(0x0070, 0x030a);
+ Tag const FrameOfReferenceTransformationMatrixType(0x0070, 0x030c);
+ Tag const RegistrationTypeCodeSequence(0x0070, 0x030d);
+ Tag const FiducialDescription(0x0070, 0x030f);
+ Tag const FiducialIdentifier(0x0070, 0x0310);
+ Tag const FiducialIdentifierCodeSequence(0x0070, 0x0311);
+ Tag const ContourUncertaintyRadius(0x0070, 0x0312);
+ Tag const UsedFiducialsSequence(0x0070, 0x0314);
+ Tag const GraphicCoordinatesDataSequence(0x0070, 0x0318);
+ Tag const FiducialUID(0x0070, 0x031a);
+ Tag const FiducialSetSequence(0x0070, 0x031c);
+ Tag const FiducialSequence(0x0070, 0x031e);
+ Tag const GraphicLayerRecommendedDisplayCIELabValue(0x0070, 0x0401);
+ Tag const BlendingSequence(0x0070, 0x0402);
+ Tag const RelativeOpacity(0x0070, 0x0403);
+ Tag const ReferencedSpatialRegistrationSequence(0x0070, 0x0404);
+ Tag const BlendingPosition(0x0070, 0x0405);
+ Tag const HangingProtocolName(0x0072, 0x0002);
+ Tag const HangingProtocolDescription(0x0072, 0x0004);
+ Tag const HangingProtocolLevel(0x0072, 0x0006);
+ Tag const HangingProtocolCreator(0x0072, 0x0008);
+ Tag const HangingProtocolCreationDateTime(0x0072, 0x000a);
+ Tag const HangingProtocolDefinitionSequence(0x0072, 0x000c);
+ Tag const HangingProtocolUserIdentificationCodeSequence(0x0072, 0x000e);
+ Tag const HangingProtocolUserGroupName(0x0072, 0x0010);
+ Tag const SourceHangingProtocolSequence(0x0072, 0x0012);
+ Tag const NumberOfPriorsReferenced(0x0072, 0x0014);
+ Tag const ImageSetsSequence(0x0072, 0x0020);
+ Tag const ImageSetSelectorSequence(0x0072, 0x0022);
+ Tag const ImageSetSelectorUsageFlag(0x0072, 0x0024);
+ Tag const SelectorAttribute(0x0072, 0x0026);
+ Tag const SelectorValueNumber(0x0072, 0x0028);
+ Tag const TimeBasedImageSetsSequence(0x0072, 0x0030);
+ Tag const ImageSetNumber(0x0072, 0x0032);
+ Tag const ImageSetSelectorCategory(0x0072, 0x0034);
+ Tag const RelativeTime(0x0072, 0x0038);
+ Tag const RelativeTimeUnits(0x0072, 0x003a);
+ Tag const AbstractPriorValue(0x0072, 0x003c);
+ Tag const AbstractPriorCodeSequence(0x0072, 0x003e);
+ Tag const ImageSetLabel(0x0072, 0x0040);
+ Tag const SelectorAttributeVR(0x0072, 0x0050);
+ Tag const SelectorSequencePointer(0x0072, 0x0052);
+ Tag const SelectorSequencePointerPrivateCreator(0x0072, 0x0054);
+ Tag const SelectorAttributePrivateCreator(0x0072, 0x0056);
+ Tag const SelectorATValue(0x0072, 0x0060);
+ Tag const SelectorCSValue(0x0072, 0x0062);
+ Tag const SelectorISValue(0x0072, 0x0064);
+ Tag const SelectorLOValue(0x0072, 0x0066);
+ Tag const SelectorLTValue(0x0072, 0x0068);
+ Tag const SelectorPNValue(0x0072, 0x006a);
+ Tag const SelectorSHValue(0x0072, 0x006c);
+ Tag const SelectorSTValue(0x0072, 0x006e);
+ Tag const SelectorUTValue(0x0072, 0x0070);
+ Tag const SelectorDSValue(0x0072, 0x0072);
+ Tag const SelectorFDValue(0x0072, 0x0074);
+ Tag const SelectorFLValue(0x0072, 0x0076);
+ Tag const SelectorULValue(0x0072, 0x0078);
+ Tag const SelectorUSValue(0x0072, 0x007a);
+ Tag const SelectorSLValue(0x0072, 0x007c);
+ Tag const SelectorSSValue(0x0072, 0x007e);
+ Tag const SelectorCodeSequenceValue(0x0072, 0x0080);
+ Tag const NumberOfScreens(0x0072, 0x0100);
+ Tag const NominalScreenDefinitionSequence(0x0072, 0x0102);
+ Tag const NumberOfVerticalPixels(0x0072, 0x0104);
+ Tag const NumberOfHorizontalPixels(0x0072, 0x0106);
+ Tag const DisplayEnvironmentSpatialPosition(0x0072, 0x0108);
+ Tag const ScreenMinimumGrayscaleBitDepth(0x0072, 0x010a);
+ Tag const ScreenMinimumColorBitDepth(0x0072, 0x010c);
+ Tag const ApplicationMaximumRepaintTime(0x0072, 0x010e);
+ Tag const DisplaySetsSequence(0x0072, 0x0200);
+ Tag const DisplaySetNumber(0x0072, 0x0202);
+ Tag const DisplaySetLabel(0x0072, 0x0203);
+ Tag const DisplaySetPresentationGroup(0x0072, 0x0204);
+ Tag const DisplaySetPresentationGroupDescription(0x0072, 0x0206);
+ Tag const PartialDataDisplayHandling(0x0072, 0x0208);
+ Tag const SynchronizedScrollingSequence(0x0072, 0x0210);
+ Tag const DisplaySetScrollingGroup(0x0072, 0x0212);
+ Tag const NavigationIndicatorSequence(0x0072, 0x0214);
+ Tag const NavigationDisplaySet(0x0072, 0x0216);
+ Tag const ReferenceDisplaySets(0x0072, 0x0218);
+ Tag const ImageBoxesSequence(0x0072, 0x0300);
+ Tag const ImageBoxNumber(0x0072, 0x0302);
+ Tag const ImageBoxLayoutType(0x0072, 0x0304);
+ Tag const ImageBoxTileHorizontalDimension(0x0072, 0x0306);
+ Tag const ImageBoxTileVerticalDimension(0x0072, 0x0308);
+ Tag const ImageBoxScrollDirection(0x0072, 0x0310);
+ Tag const ImageBoxSmallScrollType(0x0072, 0x0312);
+ Tag const ImageBoxSmallScrollAmount(0x0072, 0x0314);
+ Tag const ImageBoxLargeScrollType(0x0072, 0x0316);
+ Tag const ImageBoxLargeScrollAmount(0x0072, 0x0318);
+ Tag const ImageBoxOverlapPriority(0x0072, 0x0320);
+ Tag const CineRelativeToRealTime(0x0072, 0x0330);
+ Tag const FilterOperationsSequence(0x0072, 0x0400);
+ Tag const FilterByCategory(0x0072, 0x0402);
+ Tag const FilterByAttributePresence(0x0072, 0x0404);
+ Tag const FilterByOperator(0x0072, 0x0406);
+ Tag const StructuredDisplayBackgroundCIELabValue(0x0072, 0x0420);
+ Tag const EmptyImageBoxCIELabValue(0x0072, 0x0421);
+ Tag const StructuredDisplayImageBoxSequence(0x0072, 0x0422);
+ Tag const StructuredDisplayTextBoxSequence(0x0072, 0x0424);
+ Tag const ReferencedFirstFrameSequence(0x0072, 0x0427);
+ Tag const ImageBoxSynchronizationSequence(0x0072, 0x0430);
+ Tag const SynchronizedImageBoxList(0x0072, 0x0432);
+ Tag const TypeOfSynchronization(0x0072, 0x0434);
+ Tag const BlendingOperationType(0x0072, 0x0500);
+ Tag const ReformattingOperationType(0x0072, 0x0510);
+ Tag const ReformattingThickness(0x0072, 0x0512);
+ Tag const ReformattingInterval(0x0072, 0x0514);
+ Tag const ReformattingOperationInitialViewDirection(0x0072, 0x0516);
+ Tag const ThreeDRenderingType(0x0072, 0x0520);
+ Tag const SortingOperationsSequence(0x0072, 0x0600);
+ Tag const SortByCategory(0x0072, 0x0602);
+ Tag const SortingDirection(0x0072, 0x0604);
+ Tag const DisplaySetPatientOrientation(0x0072, 0x0700);
+ Tag const VOIType(0x0072, 0x0702);
+ Tag const PseudoColorType(0x0072, 0x0704);
+ Tag const PseudoColorPaletteInstanceReferenceSequence(0x0072, 0x0705);
+ Tag const ShowGrayscaleInverted(0x0072, 0x0706);
+ Tag const ShowImageTrueSizeFlag(0x0072, 0x0710);
+ Tag const ShowGraphicAnnotationFlag(0x0072, 0x0712);
+ Tag const ShowPatientDemographicsFlag(0x0072, 0x0714);
+ Tag const ShowAcquisitionTechniquesFlag(0x0072, 0x0716);
+ Tag const DisplaySetHorizontalJustification(0x0072, 0x0717);
+ Tag const DisplaySetVerticalJustification(0x0072, 0x0718);
+ Tag const ContinuationStartMeterset(0x0074, 0x0120);
+ Tag const ContinuationEndMeterset(0x0074, 0x0121);
+ Tag const ProcedureStepState(0x0074, 0x1000);
+ Tag const ProcedureStepProgressInformationSequence(0x0074, 0x1002);
+ Tag const ProcedureStepProgress(0x0074, 0x1004);
+ Tag const ProcedureStepProgressDescription(0x0074, 0x1006);
+ Tag const ProcedureStepCommunicationsURISequence(0x0074, 0x1008);
+ Tag const ContactURI(0x0074, 0x100a);
+ Tag const ContactDisplayName(0x0074, 0x100c);
+ Tag const ProcedureStepDiscontinuationReasonCodeSequence(0x0074, 0x100e);
+ Tag const BeamTaskSequence(0x0074, 0x1020);
+ Tag const BeamTaskType(0x0074, 0x1022);
+ Tag const BeamOrderIndexTrial(0x0074, 0x1024);
+ Tag const AutosequenceFlag(0x0074, 0x1025);
+ Tag const TableTopVerticalAdjustedPosition(0x0074, 0x1026);
+ Tag const TableTopLongitudinalAdjustedPosition(0x0074, 0x1027);
+ Tag const TableTopLateralAdjustedPosition(0x0074, 0x1028);
+ Tag const PatientSupportAdjustedAngle(0x0074, 0x102a);
+ Tag const TableTopEccentricAdjustedAngle(0x0074, 0x102b);
+ Tag const TableTopPitchAdjustedAngle(0x0074, 0x102c);
+ Tag const TableTopRollAdjustedAngle(0x0074, 0x102d);
+ Tag const DeliveryVerificationImageSequence(0x0074, 0x1030);
+ Tag const VerificationImageTiming(0x0074, 0x1032);
+ Tag const DoubleExposureFlag(0x0074, 0x1034);
+ Tag const DoubleExposureOrdering(0x0074, 0x1036);
+ Tag const DoubleExposureMetersetTrial(0x0074, 0x1038);
+ Tag const DoubleExposureFieldDeltaTrial(0x0074, 0x103a);
+ Tag const RelatedReferenceRTImageSequence(0x0074, 0x1040);
+ Tag const GeneralMachineVerificationSequence(0x0074, 0x1042);
+ Tag const ConventionalMachineVerificationSequence(0x0074, 0x1044);
+ Tag const IonMachineVerificationSequence(0x0074, 0x1046);
+ Tag const FailedAttributesSequence(0x0074, 0x1048);
+ Tag const OverriddenAttributesSequence(0x0074, 0x104a);
+ Tag const ConventionalControlPointVerificationSequence(0x0074, 0x104c);
+ Tag const IonControlPointVerificationSequence(0x0074, 0x104e);
+ Tag const AttributeOccurrenceSequence(0x0074, 0x1050);
+ Tag const AttributeOccurrencePointer(0x0074, 0x1052);
+ Tag const AttributeItemSelector(0x0074, 0x1054);
+ Tag const AttributeOccurrencePrivateCreator(0x0074, 0x1056);
+ Tag const SelectorSequencePointerItems(0x0074, 0x1057);
+ Tag const ScheduledProcedureStepPriority(0x0074, 0x1200);
+ Tag const WorklistLabel(0x0074, 0x1202);
+ Tag const ProcedureStepLabel(0x0074, 0x1204);
+ Tag const ScheduledProcessingParametersSequence(0x0074, 0x1210);
+ Tag const PerformedProcessingParametersSequence(0x0074, 0x1212);
+ Tag const UnifiedProcedureStepPerformedProcedureSequence(0x0074, 0x1216);
+ Tag const RelatedProcedureStepSequence(0x0074, 0x1220);
+ Tag const ProcedureStepRelationshipType(0x0074, 0x1222);
+ Tag const ReplacedProcedureStepSequence(0x0074, 0x1224);
+ Tag const DeletionLock(0x0074, 0x1230);
+ Tag const ReceivingAE(0x0074, 0x1234);
+ Tag const RequestingAE(0x0074, 0x1236);
+ Tag const ReasonForCancellation(0x0074, 0x1238);
+ Tag const SCPStatus(0x0074, 0x1242);
+ Tag const SubscriptionListStatus(0x0074, 0x1244);
+ Tag const UnifiedProcedureStepListStatus(0x0074, 0x1246);
+ Tag const BeamOrderIndex(0x0074, 0x1324);
+ Tag const DoubleExposureMeterset(0x0074, 0x1338);
+ Tag const DoubleExposureFieldDelta(0x0074, 0x133a);
+ Tag const ImplantAssemblyTemplateName(0x0076, 0x0001);
+ Tag const ImplantAssemblyTemplateIssuer(0x0076, 0x0003);
+ Tag const ImplantAssemblyTemplateVersion(0x0076, 0x0006);
+ Tag const ReplacedImplantAssemblyTemplateSequence(0x0076, 0x0008);
+ Tag const ImplantAssemblyTemplateType(0x0076, 0x000a);
+ Tag const OriginalImplantAssemblyTemplateSequence(0x0076, 0x000c);
+ Tag const DerivationImplantAssemblyTemplateSequence(0x0076, 0x000e);
+ Tag const ImplantAssemblyTemplateTargetAnatomySequence(0x0076, 0x0010);
+ Tag const ProcedureTypeCodeSequence(0x0076, 0x0020);
+ Tag const SurgicalTechnique(0x0076, 0x0030);
+ Tag const ComponentTypesSequence(0x0076, 0x0032);
+ Tag const ComponentTypeCodeSequence(0x0076, 0x0034);
+ Tag const ExclusiveComponentType(0x0076, 0x0036);
+ Tag const MandatoryComponentType(0x0076, 0x0038);
+ Tag const ComponentSequence(0x0076, 0x0040);
+ Tag const ComponentID(0x0076, 0x0055);
+ Tag const ComponentAssemblySequence(0x0076, 0x0060);
+ Tag const Component1ReferencedID(0x0076, 0x0070);
+ Tag const Component1ReferencedMatingFeatureSetID(0x0076, 0x0080);
+ Tag const Component1ReferencedMatingFeatureID(0x0076, 0x0090);
+ Tag const Component2ReferencedID(0x0076, 0x00a0);
+ Tag const Component2ReferencedMatingFeatureSetID(0x0076, 0x00b0);
+ Tag const Component2ReferencedMatingFeatureID(0x0076, 0x00c0);
+ Tag const ImplantTemplateGroupName(0x0078, 0x0001);
+ Tag const ImplantTemplateGroupDescription(0x0078, 0x0010);
+ Tag const ImplantTemplateGroupIssuer(0x0078, 0x0020);
+ Tag const ImplantTemplateGroupVersion(0x0078, 0x0024);
+ Tag const ReplacedImplantTemplateGroupSequence(0x0078, 0x0026);
+ Tag const ImplantTemplateGroupTargetAnatomySequence(0x0078, 0x0028);
+ Tag const ImplantTemplateGroupMembersSequence(0x0078, 0x002a);
+ Tag const ImplantTemplateGroupMemberID(0x0078, 0x002e);
+ Tag const ThreeDImplantTemplateGroupMemberMatchingPoint(0x0078, 0x0050);
+ Tag const ThreeDImplantTemplateGroupMemberMatchingAxes(0x0078, 0x0060);
+ Tag const ImplantTemplateGroupMemberMatching2DCoordinatesSequence(0x0078, 0x0070);
+ Tag const TwoDImplantTemplateGroupMemberMatchingPoint(0x0078, 0x0090);
+ Tag const TwoDImplantTemplateGroupMemberMatchingAxes(0x0078, 0x00a0);
+ Tag const ImplantTemplateGroupVariationDimensionSequence(0x0078, 0x00b0);
+ Tag const ImplantTemplateGroupVariationDimensionName(0x0078, 0x00b2);
+ Tag const ImplantTemplateGroupVariationDimensionRankSequence(0x0078, 0x00b4);
+ Tag const ReferencedImplantTemplateGroupMemberID(0x0078, 0x00b6);
+ Tag const ImplantTemplateGroupVariationDimensionRank(0x0078, 0x00b8);
+ Tag const SurfaceScanAcquisitionTypeCodeSequence(0x0080, 0x0001);
+ Tag const SurfaceScanModeCodeSequence(0x0080, 0x0002);
+ Tag const RegistrationMethodCodeSequence(0x0080, 0x0003);
+ Tag const ShotDurationTime(0x0080, 0x0004);
+ Tag const ShotOffsetTime(0x0080, 0x0005);
+ Tag const SurfacePointPresentationValueData(0x0080, 0x0006);
+ Tag const SurfacePointColorCIELabValueData(0x0080, 0x0007);
+ Tag const UVMappingSequence(0x0080, 0x0008);
+ Tag const TextureLabel(0x0080, 0x0009);
+ Tag const UValueData(0x0080, 0x0010);
+ Tag const VValueData(0x0080, 0x0011);
+ Tag const ReferencedTextureSequence(0x0080, 0x0012);
+ Tag const ReferencedSurfaceDataSequence(0x0080, 0x0013);
+ Tag const StorageMediaFileSetID(0x0088, 0x0130);
+ Tag const StorageMediaFileSetUID(0x0088, 0x0140);
+ Tag const IconImageSequence(0x0088, 0x0200);
+ Tag const TopicTitle(0x0088, 0x0904);
+ Tag const TopicSubject(0x0088, 0x0906);
+ Tag const TopicAuthor(0x0088, 0x0910);
+ Tag const TopicKeywords(0x0088, 0x0912);
+ Tag const SOPInstanceStatus(0x0100, 0x0410);
+ Tag const SOPAuthorizationDateTime(0x0100, 0x0420);
+ Tag const SOPAuthorizationComment(0x0100, 0x0424);
+ Tag const AuthorizationEquipmentCertificationNumber(0x0100, 0x0426);
+ Tag const MACIDNumber(0x0400, 0x0005);
+ Tag const MACCalculationTransferSyntaxUID(0x0400, 0x0010);
+ Tag const MACAlgorithm(0x0400, 0x0015);
+ Tag const DataElementsSigned(0x0400, 0x0020);
+ Tag const DigitalSignatureUID(0x0400, 0x0100);
+ Tag const DigitalSignatureDateTime(0x0400, 0x0105);
+ Tag const CertificateType(0x0400, 0x0110);
+ Tag const CertificateOfSigner(0x0400, 0x0115);
+ Tag const Signature(0x0400, 0x0120);
+ Tag const CertifiedTimestampType(0x0400, 0x0305);
+ Tag const CertifiedTimestamp(0x0400, 0x0310);
+ Tag const DigitalSignaturePurposeCodeSequence(0x0400, 0x0401);
+ Tag const ReferencedDigitalSignatureSequence(0x0400, 0x0402);
+ Tag const ReferencedSOPInstanceMACSequence(0x0400, 0x0403);
+ Tag const MAC(0x0400, 0x0404);
+ Tag const EncryptedAttributesSequence(0x0400, 0x0500);
+ Tag const EncryptedContentTransferSyntaxUID(0x0400, 0x0510);
+ Tag const EncryptedContent(0x0400, 0x0520);
+ Tag const ModifiedAttributesSequence(0x0400, 0x0550);
+ Tag const OriginalAttributesSequence(0x0400, 0x0561);
+ Tag const AttributeModificationDateTime(0x0400, 0x0562);
+ Tag const ModifyingSystem(0x0400, 0x0563);
+ Tag const SourceOfPreviousValues(0x0400, 0x0564);
+ Tag const ReasonForTheAttributeModification(0x0400, 0x0565);
+ Tag const NumberOfCopies(0x2000, 0x0010);
+ Tag const PrinterConfigurationSequence(0x2000, 0x001e);
+ Tag const PrintPriority(0x2000, 0x0020);
+ Tag const MediumType(0x2000, 0x0030);
+ Tag const FilmDestination(0x2000, 0x0040);
+ Tag const FilmSessionLabel(0x2000, 0x0050);
+ Tag const MemoryAllocation(0x2000, 0x0060);
+ Tag const MaximumMemoryAllocation(0x2000, 0x0061);
+ Tag const ColorImagePrintingFlag(0x2000, 0x0062);
+ Tag const CollationFlag(0x2000, 0x0063);
+ Tag const AnnotationFlag(0x2000, 0x0065);
+ Tag const ImageOverlayFlag(0x2000, 0x0067);
+ Tag const PresentationLUTFlag(0x2000, 0x0069);
+ Tag const ImageBoxPresentationLUTFlag(0x2000, 0x006a);
+ Tag const MemoryBitDepth(0x2000, 0x00a0);
+ Tag const PrintingBitDepth(0x2000, 0x00a1);
+ Tag const MediaInstalledSequence(0x2000, 0x00a2);
+ Tag const OtherMediaAvailableSequence(0x2000, 0x00a4);
+ Tag const SupportedImageDisplayFormatsSequence(0x2000, 0x00a8);
+ Tag const ReferencedFilmBoxSequence(0x2000, 0x0500);
+ Tag const ReferencedStoredPrintSequence(0x2000, 0x0510);
+ Tag const ImageDisplayFormat(0x2010, 0x0010);
+ Tag const AnnotationDisplayFormatID(0x2010, 0x0030);
+ Tag const FilmOrientation(0x2010, 0x0040);
+ Tag const FilmSizeID(0x2010, 0x0050);
+ Tag const PrinterResolutionID(0x2010, 0x0052);
+ Tag const DefaultPrinterResolutionID(0x2010, 0x0054);
+ Tag const MagnificationType(0x2010, 0x0060);
+ Tag const SmoothingType(0x2010, 0x0080);
+ Tag const DefaultMagnificationType(0x2010, 0x00a6);
+ Tag const OtherMagnificationTypesAvailable(0x2010, 0x00a7);
+ Tag const DefaultSmoothingType(0x2010, 0x00a8);
+ Tag const OtherSmoothingTypesAvailable(0x2010, 0x00a9);
+ Tag const BorderDensity(0x2010, 0x0100);
+ Tag const EmptyImageDensity(0x2010, 0x0110);
+ Tag const MinDensity(0x2010, 0x0120);
+ Tag const MaxDensity(0x2010, 0x0130);
+ Tag const Trim(0x2010, 0x0140);
+ Tag const ConfigurationInformation(0x2010, 0x0150);
+ Tag const ConfigurationInformationDescription(0x2010, 0x0152);
+ Tag const MaximumCollatedFilms(0x2010, 0x0154);
+ Tag const Illumination(0x2010, 0x015e);
+ Tag const ReflectedAmbientLight(0x2010, 0x0160);
+ Tag const PrinterPixelSpacing(0x2010, 0x0376);
+ Tag const ReferencedFilmSessionSequence(0x2010, 0x0500);
+ Tag const ReferencedImageBoxSequence(0x2010, 0x0510);
+ Tag const ReferencedBasicAnnotationBoxSequence(0x2010, 0x0520);
+ Tag const ImageBoxPosition(0x2020, 0x0010);
+ Tag const Polarity(0x2020, 0x0020);
+ Tag const RequestedImageSize(0x2020, 0x0030);
+ Tag const RequestedDecimateCropBehavior(0x2020, 0x0040);
+ Tag const RequestedResolutionID(0x2020, 0x0050);
+ Tag const RequestedImageSizeFlag(0x2020, 0x00a0);
+ Tag const DecimateCropResult(0x2020, 0x00a2);
+ Tag const BasicGrayscaleImageSequence(0x2020, 0x0110);
+ Tag const BasicColorImageSequence(0x2020, 0x0111);
+ Tag const ReferencedImageOverlayBoxSequence(0x2020, 0x0130);
+ Tag const ReferencedVOILUTBoxSequence(0x2020, 0x0140);
+ Tag const AnnotationPosition(0x2030, 0x0010);
+ Tag const TextString(0x2030, 0x0020);
+ Tag const ReferencedOverlayPlaneSequence(0x2040, 0x0010);
+ Tag const ReferencedOverlayPlaneGroups(0x2040, 0x0011);
+ Tag const OverlayPixelDataSequence(0x2040, 0x0020);
+ Tag const OverlayMagnificationType(0x2040, 0x0060);
+ Tag const OverlaySmoothingType(0x2040, 0x0070);
+ Tag const OverlayOrImageMagnification(0x2040, 0x0072);
+ Tag const MagnifyToNumberOfColumns(0x2040, 0x0074);
+ Tag const OverlayForegroundDensity(0x2040, 0x0080);
+ Tag const OverlayBackgroundDensity(0x2040, 0x0082);
+ Tag const OverlayMode(0x2040, 0x0090);
+ Tag const ThresholdDensity(0x2040, 0x0100);
+ Tag const ReferencedImageBoxSequenceRetired(0x2040, 0x0500);
+ Tag const PresentationLUTSequence(0x2050, 0x0010);
+ Tag const PresentationLUTShape(0x2050, 0x0020);
+ Tag const ReferencedPresentationLUTSequence(0x2050, 0x0500);
+ Tag const PrintJobID(0x2100, 0x0010);
+ Tag const ExecutionStatus(0x2100, 0x0020);
+ Tag const ExecutionStatusInfo(0x2100, 0x0030);
+ Tag const CreationDate(0x2100, 0x0040);
+ Tag const CreationTime(0x2100, 0x0050);
+ Tag const Originator(0x2100, 0x0070);
+ Tag const DestinationAE(0x2100, 0x0140);
+ Tag const OwnerID(0x2100, 0x0160);
+ Tag const NumberOfFilms(0x2100, 0x0170);
+ Tag const ReferencedPrintJobSequencePullStoredPrint(0x2100, 0x0500);
+ Tag const PrinterStatus(0x2110, 0x0010);
+ Tag const PrinterStatusInfo(0x2110, 0x0020);
+ Tag const PrinterName(0x2110, 0x0030);
+ Tag const PrintQueueID(0x2110, 0x0099);
+ Tag const QueueStatus(0x2120, 0x0010);
+ Tag const PrintJobDescriptionSequence(0x2120, 0x0050);
+ Tag const ReferencedPrintJobSequence(0x2120, 0x0070);
+ Tag const PrintManagementCapabilitiesSequence(0x2130, 0x0010);
+ Tag const PrinterCharacteristicsSequence(0x2130, 0x0015);
+ Tag const FilmBoxContentSequence(0x2130, 0x0030);
+ Tag const ImageBoxContentSequence(0x2130, 0x0040);
+ Tag const AnnotationContentSequence(0x2130, 0x0050);
+ Tag const ImageOverlayBoxContentSequence(0x2130, 0x0060);
+ Tag const PresentationLUTContentSequence(0x2130, 0x0080);
+ Tag const ProposedStudySequence(0x2130, 0x00a0);
+ Tag const OriginalImageSequence(0x2130, 0x00c0);
+ Tag const LabelUsingInformationExtractedFromInstances(0x2200, 0x0001);
+ Tag const LabelText(0x2200, 0x0002);
+ Tag const LabelStyleSelection(0x2200, 0x0003);
+ Tag const MediaDisposition(0x2200, 0x0004);
+ Tag const BarcodeValue(0x2200, 0x0005);
+ Tag const BarcodeSymbology(0x2200, 0x0006);
+ Tag const AllowMediaSplitting(0x2200, 0x0007);
+ Tag const IncludeNonDICOMObjects(0x2200, 0x0008);
+ Tag const IncludeDisplayApplication(0x2200, 0x0009);
+ Tag const PreserveCompositeInstancesAfterMediaCreation(0x2200, 0x000a);
+ Tag const TotalNumberOfPiecesOfMediaCreated(0x2200, 0x000b);
+ Tag const RequestedMediaApplicationProfile(0x2200, 0x000c);
+ Tag const ReferencedStorageMediaSequence(0x2200, 0x000d);
+ Tag const FailureAttributes(0x2200, 0x000e);
+ Tag const AllowLossyCompression(0x2200, 0x000f);
+ Tag const RequestPriority(0x2200, 0x0020);
+ Tag const RTImageLabel(0x3002, 0x0002);
+ Tag const RTImageName(0x3002, 0x0003);
+ Tag const RTImageDescription(0x3002, 0x0004);
+ Tag const ReportedValuesOrigin(0x3002, 0x000a);
+ Tag const RTImagePlane(0x3002, 0x000c);
+ Tag const XRayImageReceptorTranslation(0x3002, 0x000d);
+ Tag const XRayImageReceptorAngle(0x3002, 0x000e);
+ Tag const RTImageOrientation(0x3002, 0x0010);
+ Tag const ImagePlanePixelSpacing(0x3002, 0x0011);
+ Tag const RTImagePosition(0x3002, 0x0012);
+ Tag const RadiationMachineName(0x3002, 0x0020);
+ Tag const RadiationMachineSAD(0x3002, 0x0022);
+ Tag const RadiationMachineSSD(0x3002, 0x0024);
+ Tag const RTImageSID(0x3002, 0x0026);
+ Tag const SourceToReferenceObjectDistance(0x3002, 0x0028);
+ Tag const FractionNumber(0x3002, 0x0029);
+ Tag const ExposureSequence(0x3002, 0x0030);
+ Tag const MetersetExposure(0x3002, 0x0032);
+ Tag const DiaphragmPosition(0x3002, 0x0034);
+ Tag const FluenceMapSequence(0x3002, 0x0040);
+ Tag const FluenceDataSource(0x3002, 0x0041);
+ Tag const FluenceDataScale(0x3002, 0x0042);
+ Tag const PrimaryFluenceModeSequence(0x3002, 0x0050);
+ Tag const FluenceMode(0x3002, 0x0051);
+ Tag const FluenceModeID(0x3002, 0x0052);
+ Tag const DVHType(0x3004, 0x0001);
+ Tag const DoseUnits(0x3004, 0x0002);
+ Tag const DoseType(0x3004, 0x0004);
+ Tag const SpatialTransformOfDose(0x3004, 0x0005);
+ Tag const DoseComment(0x3004, 0x0006);
+ Tag const NormalizationPoint(0x3004, 0x0008);
+ Tag const DoseSummationType(0x3004, 0x000a);
+ Tag const GridFrameOffsetVector(0x3004, 0x000c);
+ Tag const DoseGridScaling(0x3004, 0x000e);
+ Tag const RTDoseROISequence(0x3004, 0x0010);
+ Tag const DoseValue(0x3004, 0x0012);
+ Tag const TissueHeterogeneityCorrection(0x3004, 0x0014);
+ Tag const DVHNormalizationPoint(0x3004, 0x0040);
+ Tag const DVHNormalizationDoseValue(0x3004, 0x0042);
+ Tag const DVHSequence(0x3004, 0x0050);
+ Tag const DVHDoseScaling(0x3004, 0x0052);
+ Tag const DVHVolumeUnits(0x3004, 0x0054);
+ Tag const DVHNumberOfBins(0x3004, 0x0056);
+ Tag const DVHData(0x3004, 0x0058);
+ Tag const DVHReferencedROISequence(0x3004, 0x0060);
+ Tag const DVHROIContributionType(0x3004, 0x0062);
+ Tag const DVHMinimumDose(0x3004, 0x0070);
+ Tag const DVHMaximumDose(0x3004, 0x0072);
+ Tag const DVHMeanDose(0x3004, 0x0074);
+ Tag const StructureSetLabel(0x3006, 0x0002);
+ Tag const StructureSetName(0x3006, 0x0004);
+ Tag const StructureSetDescription(0x3006, 0x0006);
+ Tag const StructureSetDate(0x3006, 0x0008);
+ Tag const StructureSetTime(0x3006, 0x0009);
+ Tag const ReferencedFrameOfReferenceSequence(0x3006, 0x0010);
+ Tag const RTReferencedStudySequence(0x3006, 0x0012);
+ Tag const RTReferencedSeriesSequence(0x3006, 0x0014);
+ Tag const ContourImageSequence(0x3006, 0x0016);
+ Tag const PredecessorStructureSetSequence(0x3006, 0x0018);
+ Tag const StructureSetROISequence(0x3006, 0x0020);
+ Tag const ROINumber(0x3006, 0x0022);
+ Tag const ReferencedFrameOfReferenceUID(0x3006, 0x0024);
+ Tag const ROIName(0x3006, 0x0026);
+ Tag const ROIDescription(0x3006, 0x0028);
+ Tag const ROIDisplayColor(0x3006, 0x002a);
+ Tag const ROIVolume(0x3006, 0x002c);
+ Tag const RTRelatedROISequence(0x3006, 0x0030);
+ Tag const RTROIRelationship(0x3006, 0x0033);
+ Tag const ROIGenerationAlgorithm(0x3006, 0x0036);
+ Tag const ROIGenerationDescription(0x3006, 0x0038);
+ Tag const ROIContourSequence(0x3006, 0x0039);
+ Tag const ContourSequence(0x3006, 0x0040);
+ Tag const ContourGeometricType(0x3006, 0x0042);
+ Tag const ContourSlabThickness(0x3006, 0x0044);
+ Tag const ContourOffsetVector(0x3006, 0x0045);
+ Tag const NumberOfContourPoints(0x3006, 0x0046);
+ Tag const ContourNumber(0x3006, 0x0048);
+ Tag const AttachedContours(0x3006, 0x0049);
+ Tag const ContourData(0x3006, 0x0050);
+ Tag const RTROIObservationsSequence(0x3006, 0x0080);
+ Tag const ObservationNumber(0x3006, 0x0082);
+ Tag const ReferencedROINumber(0x3006, 0x0084);
+ Tag const ROIObservationLabel(0x3006, 0x0085);
+ Tag const RTROIIdentificationCodeSequence(0x3006, 0x0086);
+ Tag const ROIObservationDescription(0x3006, 0x0088);
+ Tag const RelatedRTROIObservationsSequence(0x3006, 0x00a0);
+ Tag const RTROIInterpretedType(0x3006, 0x00a4);
+ Tag const ROIInterpreter(0x3006, 0x00a6);
+ Tag const ROIPhysicalPropertiesSequence(0x3006, 0x00b0);
+ Tag const ROIPhysicalProperty(0x3006, 0x00b2);
+ Tag const ROIPhysicalPropertyValue(0x3006, 0x00b4);
+ Tag const ROIElementalCompositionSequence(0x3006, 0x00b6);
+ Tag const ROIElementalCompositionAtomicNumber(0x3006, 0x00b7);
+ Tag const ROIElementalCompositionAtomicMassFraction(0x3006, 0x00b8);
+ Tag const AdditionalRTROIIdentificationCodeSequence(0x3006, 0x00b9);
+ Tag const FrameOfReferenceRelationshipSequence(0x3006, 0x00c0);
+ Tag const RelatedFrameOfReferenceUID(0x3006, 0x00c2);
+ Tag const FrameOfReferenceTransformationType(0x3006, 0x00c4);
+ Tag const FrameOfReferenceTransformationMatrix(0x3006, 0x00c6);
+ Tag const FrameOfReferenceTransformationComment(0x3006, 0x00c8);
+ Tag const MeasuredDoseReferenceSequence(0x3008, 0x0010);
+ Tag const MeasuredDoseDescription(0x3008, 0x0012);
+ Tag const MeasuredDoseType(0x3008, 0x0014);
+ Tag const MeasuredDoseValue(0x3008, 0x0016);
+ Tag const TreatmentSessionBeamSequence(0x3008, 0x0020);
+ Tag const TreatmentSessionIonBeamSequence(0x3008, 0x0021);
+ Tag const CurrentFractionNumber(0x3008, 0x0022);
+ Tag const TreatmentControlPointDate(0x3008, 0x0024);
+ Tag const TreatmentControlPointTime(0x3008, 0x0025);
+ Tag const TreatmentTerminationStatus(0x3008, 0x002a);
+ Tag const TreatmentTerminationCode(0x3008, 0x002b);
+ Tag const TreatmentVerificationStatus(0x3008, 0x002c);
+ Tag const ReferencedTreatmentRecordSequence(0x3008, 0x0030);
+ Tag const SpecifiedPrimaryMeterset(0x3008, 0x0032);
+ Tag const SpecifiedSecondaryMeterset(0x3008, 0x0033);
+ Tag const DeliveredPrimaryMeterset(0x3008, 0x0036);
+ Tag const DeliveredSecondaryMeterset(0x3008, 0x0037);
+ Tag const SpecifiedTreatmentTime(0x3008, 0x003a);
+ Tag const DeliveredTreatmentTime(0x3008, 0x003b);
+ Tag const ControlPointDeliverySequence(0x3008, 0x0040);
+ Tag const IonControlPointDeliverySequence(0x3008, 0x0041);
+ Tag const SpecifiedMeterset(0x3008, 0x0042);
+ Tag const DeliveredMeterset(0x3008, 0x0044);
+ Tag const MetersetRateSet(0x3008, 0x0045);
+ Tag const MetersetRateDelivered(0x3008, 0x0046);
+ Tag const ScanSpotMetersetsDelivered(0x3008, 0x0047);
+ Tag const DoseRateDelivered(0x3008, 0x0048);
+ Tag const TreatmentSummaryCalculatedDoseReferenceSequence(0x3008, 0x0050);
+ Tag const CumulativeDoseToDoseReference(0x3008, 0x0052);
+ Tag const FirstTreatmentDate(0x3008, 0x0054);
+ Tag const MostRecentTreatmentDate(0x3008, 0x0056);
+ Tag const NumberOfFractionsDelivered(0x3008, 0x005a);
+ Tag const OverrideSequence(0x3008, 0x0060);
+ Tag const ParameterSequencePointer(0x3008, 0x0061);
+ Tag const OverrideParameterPointer(0x3008, 0x0062);
+ Tag const ParameterItemIndex(0x3008, 0x0063);
+ Tag const MeasuredDoseReferenceNumber(0x3008, 0x0064);
+ Tag const ParameterPointer(0x3008, 0x0065);
+ Tag const OverrideReason(0x3008, 0x0066);
+ Tag const CorrectedParameterSequence(0x3008, 0x0068);
+ Tag const CorrectionValue(0x3008, 0x006a);
+ Tag const CalculatedDoseReferenceSequence(0x3008, 0x0070);
+ Tag const CalculatedDoseReferenceNumber(0x3008, 0x0072);
+ Tag const CalculatedDoseReferenceDescription(0x3008, 0x0074);
+ Tag const CalculatedDoseReferenceDoseValue(0x3008, 0x0076);
+ Tag const StartMeterset(0x3008, 0x0078);
+ Tag const EndMeterset(0x3008, 0x007a);
+ Tag const ReferencedMeasuredDoseReferenceSequence(0x3008, 0x0080);
+ Tag const ReferencedMeasuredDoseReferenceNumber(0x3008, 0x0082);
+ Tag const ReferencedCalculatedDoseReferenceSequence(0x3008, 0x0090);
+ Tag const ReferencedCalculatedDoseReferenceNumber(0x3008, 0x0092);
+ Tag const BeamLimitingDeviceLeafPairsSequence(0x3008, 0x00a0);
+ Tag const RecordedWedgeSequence(0x3008, 0x00b0);
+ Tag const RecordedCompensatorSequence(0x3008, 0x00c0);
+ Tag const RecordedBlockSequence(0x3008, 0x00d0);
+ Tag const TreatmentSummaryMeasuredDoseReferenceSequence(0x3008, 0x00e0);
+ Tag const RecordedSnoutSequence(0x3008, 0x00f0);
+ Tag const RecordedRangeShifterSequence(0x3008, 0x00f2);
+ Tag const RecordedLateralSpreadingDeviceSequence(0x3008, 0x00f4);
+ Tag const RecordedRangeModulatorSequence(0x3008, 0x00f6);
+ Tag const RecordedSourceSequence(0x3008, 0x0100);
+ Tag const SourceSerialNumber(0x3008, 0x0105);
+ Tag const TreatmentSessionApplicationSetupSequence(0x3008, 0x0110);
+ Tag const ApplicationSetupCheck(0x3008, 0x0116);
+ Tag const RecordedBrachyAccessoryDeviceSequence(0x3008, 0x0120);
+ Tag const ReferencedBrachyAccessoryDeviceNumber(0x3008, 0x0122);
+ Tag const RecordedChannelSequence(0x3008, 0x0130);
+ Tag const SpecifiedChannelTotalTime(0x3008, 0x0132);
+ Tag const DeliveredChannelTotalTime(0x3008, 0x0134);
+ Tag const SpecifiedNumberOfPulses(0x3008, 0x0136);
+ Tag const DeliveredNumberOfPulses(0x3008, 0x0138);
+ Tag const SpecifiedPulseRepetitionInterval(0x3008, 0x013a);
+ Tag const DeliveredPulseRepetitionInterval(0x3008, 0x013c);
+ Tag const RecordedSourceApplicatorSequence(0x3008, 0x0140);
+ Tag const ReferencedSourceApplicatorNumber(0x3008, 0x0142);
+ Tag const RecordedChannelShieldSequence(0x3008, 0x0150);
+ Tag const ReferencedChannelShieldNumber(0x3008, 0x0152);
+ Tag const BrachyControlPointDeliveredSequence(0x3008, 0x0160);
+ Tag const SafePositionExitDate(0x3008, 0x0162);
+ Tag const SafePositionExitTime(0x3008, 0x0164);
+ Tag const SafePositionReturnDate(0x3008, 0x0166);
+ Tag const SafePositionReturnTime(0x3008, 0x0168);
+ Tag const PulseSpecificBrachyControlPointDeliveredSequence(0x3008, 0x0171);
+ Tag const PulseNumber(0x3008, 0x0172);
+ Tag const BrachyPulseControlPointDeliveredSequence(0x3008, 0x0173);
+ Tag const CurrentTreatmentStatus(0x3008, 0x0200);
+ Tag const TreatmentStatusComment(0x3008, 0x0202);
+ Tag const FractionGroupSummarySequence(0x3008, 0x0220);
+ Tag const ReferencedFractionNumber(0x3008, 0x0223);
+ Tag const FractionGroupType(0x3008, 0x0224);
+ Tag const BeamStopperPosition(0x3008, 0x0230);
+ Tag const FractionStatusSummarySequence(0x3008, 0x0240);
+ Tag const TreatmentDate(0x3008, 0x0250);
+ Tag const TreatmentTime(0x3008, 0x0251);
+ Tag const RTPlanLabel(0x300a, 0x0002);
+ Tag const RTPlanName(0x300a, 0x0003);
+ Tag const RTPlanDescription(0x300a, 0x0004);
+ Tag const RTPlanDate(0x300a, 0x0006);
+ Tag const RTPlanTime(0x300a, 0x0007);
+ Tag const TreatmentProtocols(0x300a, 0x0009);
+ Tag const PlanIntent(0x300a, 0x000a);
+ Tag const TreatmentSites(0x300a, 0x000b);
+ Tag const RTPlanGeometry(0x300a, 0x000c);
+ Tag const PrescriptionDescription(0x300a, 0x000e);
+ Tag const DoseReferenceSequence(0x300a, 0x0010);
+ Tag const DoseReferenceNumber(0x300a, 0x0012);
+ Tag const DoseReferenceUID(0x300a, 0x0013);
+ Tag const DoseReferenceStructureType(0x300a, 0x0014);
+ Tag const NominalBeamEnergyUnit(0x300a, 0x0015);
+ Tag const DoseReferenceDescription(0x300a, 0x0016);
+ Tag const DoseReferencePointCoordinates(0x300a, 0x0018);
+ Tag const NominalPriorDose(0x300a, 0x001a);
+ Tag const DoseReferenceType(0x300a, 0x0020);
+ Tag const ConstraintWeight(0x300a, 0x0021);
+ Tag const DeliveryWarningDose(0x300a, 0x0022);
+ Tag const DeliveryMaximumDose(0x300a, 0x0023);
+ Tag const TargetMinimumDose(0x300a, 0x0025);
+ Tag const TargetPrescriptionDose(0x300a, 0x0026);
+ Tag const TargetMaximumDose(0x300a, 0x0027);
+ Tag const TargetUnderdoseVolumeFraction(0x300a, 0x0028);
+ Tag const OrganAtRiskFullVolumeDose(0x300a, 0x002a);
+ Tag const OrganAtRiskLimitDose(0x300a, 0x002b);
+ Tag const OrganAtRiskMaximumDose(0x300a, 0x002c);
+ Tag const OrganAtRiskOverdoseVolumeFraction(0x300a, 0x002d);
+ Tag const ToleranceTableSequence(0x300a, 0x0040);
+ Tag const ToleranceTableNumber(0x300a, 0x0042);
+ Tag const ToleranceTableLabel(0x300a, 0x0043);
+ Tag const GantryAngleTolerance(0x300a, 0x0044);
+ Tag const BeamLimitingDeviceAngleTolerance(0x300a, 0x0046);
+ Tag const BeamLimitingDeviceToleranceSequence(0x300a, 0x0048);
+ Tag const BeamLimitingDevicePositionTolerance(0x300a, 0x004a);
+ Tag const SnoutPositionTolerance(0x300a, 0x004b);
+ Tag const PatientSupportAngleTolerance(0x300a, 0x004c);
+ Tag const TableTopEccentricAngleTolerance(0x300a, 0x004e);
+ Tag const TableTopPitchAngleTolerance(0x300a, 0x004f);
+ Tag const TableTopRollAngleTolerance(0x300a, 0x0050);
+ Tag const TableTopVerticalPositionTolerance(0x300a, 0x0051);
+ Tag const TableTopLongitudinalPositionTolerance(0x300a, 0x0052);
+ Tag const TableTopLateralPositionTolerance(0x300a, 0x0053);
+ Tag const RTPlanRelationship(0x300a, 0x0055);
+ Tag const FractionGroupSequence(0x300a, 0x0070);
+ Tag const FractionGroupNumber(0x300a, 0x0071);
+ Tag const FractionGroupDescription(0x300a, 0x0072);
+ Tag const NumberOfFractionsPlanned(0x300a, 0x0078);
+ Tag const NumberOfFractionPatternDigitsPerDay(0x300a, 0x0079);
+ Tag const RepeatFractionCycleLength(0x300a, 0x007a);
+ Tag const FractionPattern(0x300a, 0x007b);
+ Tag const NumberOfBeams(0x300a, 0x0080);
+ Tag const BeamDoseSpecificationPoint(0x300a, 0x0082);
+ Tag const BeamDose(0x300a, 0x0084);
+ Tag const BeamMeterset(0x300a, 0x0086);
+ Tag const BeamDosePointDepth(0x300a, 0x0088);
+ Tag const BeamDosePointEquivalentDepth(0x300a, 0x0089);
+ Tag const BeamDosePointSSD(0x300a, 0x008a);
+ Tag const BeamDoseMeaning(0x300a, 0x008b);
+ Tag const BeamDoseVerificationControlPointSequence(0x300a, 0x008c);
+ Tag const AverageBeamDosePointDepth(0x300a, 0x008d);
+ Tag const AverageBeamDosePointEquivalentDepth(0x300a, 0x008e);
+ Tag const AverageBeamDosePointSSD(0x300a, 0x008f);
+ Tag const NumberOfBrachyApplicationSetups(0x300a, 0x00a0);
+ Tag const BrachyApplicationSetupDoseSpecificationPoint(0x300a, 0x00a2);
+ Tag const BrachyApplicationSetupDose(0x300a, 0x00a4);
+ Tag const BeamSequence(0x300a, 0x00b0);
+ Tag const TreatmentMachineName(0x300a, 0x00b2);
+ Tag const PrimaryDosimeterUnit(0x300a, 0x00b3);
+ Tag const SourceAxisDistance(0x300a, 0x00b4);
+ Tag const BeamLimitingDeviceSequence(0x300a, 0x00b6);
+ Tag const RTBeamLimitingDeviceType(0x300a, 0x00b8);
+ Tag const SourceToBeamLimitingDeviceDistance(0x300a, 0x00ba);
+ Tag const IsocenterToBeamLimitingDeviceDistance(0x300a, 0x00bb);
+ Tag const NumberOfLeafJawPairs(0x300a, 0x00bc);
+ Tag const LeafPositionBoundaries(0x300a, 0x00be);
+ Tag const BeamNumber(0x300a, 0x00c0);
+ Tag const BeamName(0x300a, 0x00c2);
+ Tag const BeamDescription(0x300a, 0x00c3);
+ Tag const BeamType(0x300a, 0x00c4);
+ Tag const BeamDeliveryDurationLimit(0x300a, 0x00c5);
+ Tag const RadiationType(0x300a, 0x00c6);
+ Tag const HighDoseTechniqueType(0x300a, 0x00c7);
+ Tag const ReferenceImageNumber(0x300a, 0x00c8);
+ Tag const PlannedVerificationImageSequence(0x300a, 0x00ca);
+ Tag const ImagingDeviceSpecificAcquisitionParameters(0x300a, 0x00cc);
+ Tag const TreatmentDeliveryType(0x300a, 0x00ce);
+ Tag const NumberOfWedges(0x300a, 0x00d0);
+ Tag const WedgeSequence(0x300a, 0x00d1);
+ Tag const WedgeNumber(0x300a, 0x00d2);
+ Tag const WedgeType(0x300a, 0x00d3);
+ Tag const WedgeID(0x300a, 0x00d4);
+ Tag const WedgeAngle(0x300a, 0x00d5);
+ Tag const WedgeFactor(0x300a, 0x00d6);
+ Tag const TotalWedgeTrayWaterEquivalentThickness(0x300a, 0x00d7);
+ Tag const WedgeOrientation(0x300a, 0x00d8);
+ Tag const IsocenterToWedgeTrayDistance(0x300a, 0x00d9);
+ Tag const SourceToWedgeTrayDistance(0x300a, 0x00da);
+ Tag const WedgeThinEdgePosition(0x300a, 0x00db);
+ Tag const BolusID(0x300a, 0x00dc);
+ Tag const BolusDescription(0x300a, 0x00dd);
+ Tag const EffectiveWedgeAngle(0x300a, 0x00de);
+ Tag const NumberOfCompensators(0x300a, 0x00e0);
+ Tag const MaterialID(0x300a, 0x00e1);
+ Tag const TotalCompensatorTrayFactor(0x300a, 0x00e2);
+ Tag const CompensatorSequence(0x300a, 0x00e3);
+ Tag const CompensatorNumber(0x300a, 0x00e4);
+ Tag const CompensatorID(0x300a, 0x00e5);
+ Tag const SourceToCompensatorTrayDistance(0x300a, 0x00e6);
+ Tag const CompensatorRows(0x300a, 0x00e7);
+ Tag const CompensatorColumns(0x300a, 0x00e8);
+ Tag const CompensatorPixelSpacing(0x300a, 0x00e9);
+ Tag const CompensatorPosition(0x300a, 0x00ea);
+ Tag const CompensatorTransmissionData(0x300a, 0x00eb);
+ Tag const CompensatorThicknessData(0x300a, 0x00ec);
+ Tag const NumberOfBoli(0x300a, 0x00ed);
+ Tag const CompensatorType(0x300a, 0x00ee);
+ Tag const CompensatorTrayID(0x300a, 0x00ef);
+ Tag const NumberOfBlocks(0x300a, 0x00f0);
+ Tag const TotalBlockTrayFactor(0x300a, 0x00f2);
+ Tag const TotalBlockTrayWaterEquivalentThickness(0x300a, 0x00f3);
+ Tag const BlockSequence(0x300a, 0x00f4);
+ Tag const BlockTrayID(0x300a, 0x00f5);
+ Tag const SourceToBlockTrayDistance(0x300a, 0x00f6);
+ Tag const IsocenterToBlockTrayDistance(0x300a, 0x00f7);
+ Tag const BlockType(0x300a, 0x00f8);
+ Tag const AccessoryCode(0x300a, 0x00f9);
+ Tag const BlockDivergence(0x300a, 0x00fa);
+ Tag const BlockMountingPosition(0x300a, 0x00fb);
+ Tag const BlockNumber(0x300a, 0x00fc);
+ Tag const BlockName(0x300a, 0x00fe);
+ Tag const BlockThickness(0x300a, 0x0100);
+ Tag const BlockTransmission(0x300a, 0x0102);
+ Tag const BlockNumberOfPoints(0x300a, 0x0104);
+ Tag const BlockData(0x300a, 0x0106);
+ Tag const ApplicatorSequence(0x300a, 0x0107);
+ Tag const ApplicatorID(0x300a, 0x0108);
+ Tag const ApplicatorType(0x300a, 0x0109);
+ Tag const ApplicatorDescription(0x300a, 0x010a);
+ Tag const CumulativeDoseReferenceCoefficient(0x300a, 0x010c);
+ Tag const FinalCumulativeMetersetWeight(0x300a, 0x010e);
+ Tag const NumberOfControlPoints(0x300a, 0x0110);
+ Tag const ControlPointSequence(0x300a, 0x0111);
+ Tag const ControlPointIndex(0x300a, 0x0112);
+ Tag const NominalBeamEnergy(0x300a, 0x0114);
+ Tag const DoseRateSet(0x300a, 0x0115);
+ Tag const WedgePositionSequence(0x300a, 0x0116);
+ Tag const WedgePosition(0x300a, 0x0118);
+ Tag const BeamLimitingDevicePositionSequence(0x300a, 0x011a);
+ Tag const LeafJawPositions(0x300a, 0x011c);
+ Tag const GantryAngle(0x300a, 0x011e);
+ Tag const GantryRotationDirection(0x300a, 0x011f);
+ Tag const BeamLimitingDeviceAngle(0x300a, 0x0120);
+ Tag const BeamLimitingDeviceRotationDirection(0x300a, 0x0121);
+ Tag const PatientSupportAngle(0x300a, 0x0122);
+ Tag const PatientSupportRotationDirection(0x300a, 0x0123);
+ Tag const TableTopEccentricAxisDistance(0x300a, 0x0124);
+ Tag const TableTopEccentricAngle(0x300a, 0x0125);
+ Tag const TableTopEccentricRotationDirection(0x300a, 0x0126);
+ Tag const TableTopVerticalPosition(0x300a, 0x0128);
+ Tag const TableTopLongitudinalPosition(0x300a, 0x0129);
+ Tag const TableTopLateralPosition(0x300a, 0x012a);
+ Tag const IsocenterPosition(0x300a, 0x012c);
+ Tag const SurfaceEntryPoint(0x300a, 0x012e);
+ Tag const SourceToSurfaceDistance(0x300a, 0x0130);
+ Tag const AverageBeamDosePointSourceToExternalContourSurfaceDistance(0x300a, 0x0131);
+ Tag const SourceToExternalContourDistance(0x300a, 0x0132);
+ Tag const ExternalContourEntryPoint(0x300a, 0x0133);
+ Tag const CumulativeMetersetWeight(0x300a, 0x0134);
+ Tag const TableTopPitchAngle(0x300a, 0x0140);
+ Tag const TableTopPitchRotationDirection(0x300a, 0x0142);
+ Tag const TableTopRollAngle(0x300a, 0x0144);
+ Tag const TableTopRollRotationDirection(0x300a, 0x0146);
+ Tag const HeadFixationAngle(0x300a, 0x0148);
+ Tag const GantryPitchAngle(0x300a, 0x014a);
+ Tag const GantryPitchRotationDirection(0x300a, 0x014c);
+ Tag const GantryPitchAngleTolerance(0x300a, 0x014e);
+ Tag const PatientSetupSequence(0x300a, 0x0180);
+ Tag const PatientSetupNumber(0x300a, 0x0182);
+ Tag const PatientSetupLabel(0x300a, 0x0183);
+ Tag const PatientAdditionalPosition(0x300a, 0x0184);
+ Tag const FixationDeviceSequence(0x300a, 0x0190);
+ Tag const FixationDeviceType(0x300a, 0x0192);
+ Tag const FixationDeviceLabel(0x300a, 0x0194);
+ Tag const FixationDeviceDescription(0x300a, 0x0196);
+ Tag const FixationDevicePosition(0x300a, 0x0198);
+ Tag const FixationDevicePitchAngle(0x300a, 0x0199);
+ Tag const FixationDeviceRollAngle(0x300a, 0x019a);
+ Tag const ShieldingDeviceSequence(0x300a, 0x01a0);
+ Tag const ShieldingDeviceType(0x300a, 0x01a2);
+ Tag const ShieldingDeviceLabel(0x300a, 0x01a4);
+ Tag const ShieldingDeviceDescription(0x300a, 0x01a6);
+ Tag const ShieldingDevicePosition(0x300a, 0x01a8);
+ Tag const SetupTechnique(0x300a, 0x01b0);
+ Tag const SetupTechniqueDescription(0x300a, 0x01b2);
+ Tag const SetupDeviceSequence(0x300a, 0x01b4);
+ Tag const SetupDeviceType(0x300a, 0x01b6);
+ Tag const SetupDeviceLabel(0x300a, 0x01b8);
+ Tag const SetupDeviceDescription(0x300a, 0x01ba);
+ Tag const SetupDeviceParameter(0x300a, 0x01bc);
+ Tag const SetupReferenceDescription(0x300a, 0x01d0);
+ Tag const TableTopVerticalSetupDisplacement(0x300a, 0x01d2);
+ Tag const TableTopLongitudinalSetupDisplacement(0x300a, 0x01d4);
+ Tag const TableTopLateralSetupDisplacement(0x300a, 0x01d6);
+ Tag const BrachyTreatmentTechnique(0x300a, 0x0200);
+ Tag const BrachyTreatmentType(0x300a, 0x0202);
+ Tag const TreatmentMachineSequence(0x300a, 0x0206);
+ Tag const SourceSequence(0x300a, 0x0210);
+ Tag const SourceNumber(0x300a, 0x0212);
+ Tag const SourceType(0x300a, 0x0214);
+ Tag const SourceManufacturer(0x300a, 0x0216);
+ Tag const ActiveSourceDiameter(0x300a, 0x0218);
+ Tag const ActiveSourceLength(0x300a, 0x021a);
+ Tag const SourceModelID(0x300a, 0x021b);
+ Tag const SourceDescription(0x300a, 0x021c);
+ Tag const SourceEncapsulationNominalThickness(0x300a, 0x0222);
+ Tag const SourceEncapsulationNominalTransmission(0x300a, 0x0224);
+ Tag const SourceIsotopeName(0x300a, 0x0226);
+ Tag const SourceIsotopeHalfLife(0x300a, 0x0228);
+ Tag const SourceStrengthUnits(0x300a, 0x0229);
+ Tag const ReferenceAirKermaRate(0x300a, 0x022a);
+ Tag const SourceStrength(0x300a, 0x022b);
+ Tag const SourceStrengthReferenceDate(0x300a, 0x022c);
+ Tag const SourceStrengthReferenceTime(0x300a, 0x022e);
+ Tag const ApplicationSetupSequence(0x300a, 0x0230);
+ Tag const ApplicationSetupType(0x300a, 0x0232);
+ Tag const ApplicationSetupNumber(0x300a, 0x0234);
+ Tag const ApplicationSetupName(0x300a, 0x0236);
+ Tag const ApplicationSetupManufacturer(0x300a, 0x0238);
+ Tag const TemplateNumber(0x300a, 0x0240);
+ Tag const TemplateType(0x300a, 0x0242);
+ Tag const TemplateName(0x300a, 0x0244);
+ Tag const TotalReferenceAirKerma(0x300a, 0x0250);
+ Tag const BrachyAccessoryDeviceSequence(0x300a, 0x0260);
+ Tag const BrachyAccessoryDeviceNumber(0x300a, 0x0262);
+ Tag const BrachyAccessoryDeviceID(0x300a, 0x0263);
+ Tag const BrachyAccessoryDeviceType(0x300a, 0x0264);
+ Tag const BrachyAccessoryDeviceName(0x300a, 0x0266);
+ Tag const BrachyAccessoryDeviceNominalThickness(0x300a, 0x026a);
+ Tag const BrachyAccessoryDeviceNominalTransmission(0x300a, 0x026c);
+ Tag const ChannelSequence(0x300a, 0x0280);
+ Tag const ChannelNumber(0x300a, 0x0282);
+ Tag const ChannelLength(0x300a, 0x0284);
+ Tag const ChannelTotalTime(0x300a, 0x0286);
+ Tag const SourceMovementType(0x300a, 0x0288);
+ Tag const NumberOfPulses(0x300a, 0x028a);
+ Tag const PulseRepetitionInterval(0x300a, 0x028c);
+ Tag const SourceApplicatorNumber(0x300a, 0x0290);
+ Tag const SourceApplicatorID(0x300a, 0x0291);
+ Tag const SourceApplicatorType(0x300a, 0x0292);
+ Tag const SourceApplicatorName(0x300a, 0x0294);
+ Tag const SourceApplicatorLength(0x300a, 0x0296);
+ Tag const SourceApplicatorManufacturer(0x300a, 0x0298);
+ Tag const SourceApplicatorWallNominalThickness(0x300a, 0x029c);
+ Tag const SourceApplicatorWallNominalTransmission(0x300a, 0x029e);
+ Tag const SourceApplicatorStepSize(0x300a, 0x02a0);
+ Tag const TransferTubeNumber(0x300a, 0x02a2);
+ Tag const TransferTubeLength(0x300a, 0x02a4);
+ Tag const ChannelShieldSequence(0x300a, 0x02b0);
+ Tag const ChannelShieldNumber(0x300a, 0x02b2);
+ Tag const ChannelShieldID(0x300a, 0x02b3);
+ Tag const ChannelShieldName(0x300a, 0x02b4);
+ Tag const ChannelShieldNominalThickness(0x300a, 0x02b8);
+ Tag const ChannelShieldNominalTransmission(0x300a, 0x02ba);
+ Tag const FinalCumulativeTimeWeight(0x300a, 0x02c8);
+ Tag const BrachyControlPointSequence(0x300a, 0x02d0);
+ Tag const ControlPointRelativePosition(0x300a, 0x02d2);
+ Tag const ControlPoint3DPosition(0x300a, 0x02d4);
+ Tag const CumulativeTimeWeight(0x300a, 0x02d6);
+ Tag const CompensatorDivergence(0x300a, 0x02e0);
+ Tag const CompensatorMountingPosition(0x300a, 0x02e1);
+ Tag const SourceToCompensatorDistance(0x300a, 0x02e2);
+ Tag const TotalCompensatorTrayWaterEquivalentThickness(0x300a, 0x02e3);
+ Tag const IsocenterToCompensatorTrayDistance(0x300a, 0x02e4);
+ Tag const CompensatorColumnOffset(0x300a, 0x02e5);
+ Tag const IsocenterToCompensatorDistances(0x300a, 0x02e6);
+ Tag const CompensatorRelativeStoppingPowerRatio(0x300a, 0x02e7);
+ Tag const CompensatorMillingToolDiameter(0x300a, 0x02e8);
+ Tag const IonRangeCompensatorSequence(0x300a, 0x02ea);
+ Tag const CompensatorDescription(0x300a, 0x02eb);
+ Tag const RadiationMassNumber(0x300a, 0x0302);
+ Tag const RadiationAtomicNumber(0x300a, 0x0304);
+ Tag const RadiationChargeState(0x300a, 0x0306);
+ Tag const ScanMode(0x300a, 0x0308);
+ Tag const VirtualSourceAxisDistances(0x300a, 0x030a);
+ Tag const SnoutSequence(0x300a, 0x030c);
+ Tag const SnoutPosition(0x300a, 0x030d);
+ Tag const SnoutID(0x300a, 0x030f);
+ Tag const NumberOfRangeShifters(0x300a, 0x0312);
+ Tag const RangeShifterSequence(0x300a, 0x0314);
+ Tag const RangeShifterNumber(0x300a, 0x0316);
+ Tag const RangeShifterID(0x300a, 0x0318);
+ Tag const RangeShifterType(0x300a, 0x0320);
+ Tag const RangeShifterDescription(0x300a, 0x0322);
+ Tag const NumberOfLateralSpreadingDevices(0x300a, 0x0330);
+ Tag const LateralSpreadingDeviceSequence(0x300a, 0x0332);
+ Tag const LateralSpreadingDeviceNumber(0x300a, 0x0334);
+ Tag const LateralSpreadingDeviceID(0x300a, 0x0336);
+ Tag const LateralSpreadingDeviceType(0x300a, 0x0338);
+ Tag const LateralSpreadingDeviceDescription(0x300a, 0x033a);
+ Tag const LateralSpreadingDeviceWaterEquivalentThickness(0x300a, 0x033c);
+ Tag const NumberOfRangeModulators(0x300a, 0x0340);
+ Tag const RangeModulatorSequence(0x300a, 0x0342);
+ Tag const RangeModulatorNumber(0x300a, 0x0344);
+ Tag const RangeModulatorID(0x300a, 0x0346);
+ Tag const RangeModulatorType(0x300a, 0x0348);
+ Tag const RangeModulatorDescription(0x300a, 0x034a);
+ Tag const BeamCurrentModulationID(0x300a, 0x034c);
+ Tag const PatientSupportType(0x300a, 0x0350);
+ Tag const PatientSupportID(0x300a, 0x0352);
+ Tag const PatientSupportAccessoryCode(0x300a, 0x0354);
+ Tag const FixationLightAzimuthalAngle(0x300a, 0x0356);
+ Tag const FixationLightPolarAngle(0x300a, 0x0358);
+ Tag const MetersetRate(0x300a, 0x035a);
+ Tag const RangeShifterSettingsSequence(0x300a, 0x0360);
+ Tag const RangeShifterSetting(0x300a, 0x0362);
+ Tag const IsocenterToRangeShifterDistance(0x300a, 0x0364);
+ Tag const RangeShifterWaterEquivalentThickness(0x300a, 0x0366);
+ Tag const LateralSpreadingDeviceSettingsSequence(0x300a, 0x0370);
+ Tag const LateralSpreadingDeviceSetting(0x300a, 0x0372);
+ Tag const IsocenterToLateralSpreadingDeviceDistance(0x300a, 0x0374);
+ Tag const RangeModulatorSettingsSequence(0x300a, 0x0380);
+ Tag const RangeModulatorGatingStartValue(0x300a, 0x0382);
+ Tag const RangeModulatorGatingStopValue(0x300a, 0x0384);
+ Tag const RangeModulatorGatingStartWaterEquivalentThickness(0x300a, 0x0386);
+ Tag const RangeModulatorGatingStopWaterEquivalentThickness(0x300a, 0x0388);
+ Tag const IsocenterToRangeModulatorDistance(0x300a, 0x038a);
+ Tag const ScanSpotTuneID(0x300a, 0x0390);
+ Tag const NumberOfScanSpotPositions(0x300a, 0x0392);
+ Tag const ScanSpotPositionMap(0x300a, 0x0394);
+ Tag const ScanSpotMetersetWeights(0x300a, 0x0396);
+ Tag const ScanningSpotSize(0x300a, 0x0398);
+ Tag const NumberOfPaintings(0x300a, 0x039a);
+ Tag const IonToleranceTableSequence(0x300a, 0x03a0);
+ Tag const IonBeamSequence(0x300a, 0x03a2);
+ Tag const IonBeamLimitingDeviceSequence(0x300a, 0x03a4);
+ Tag const IonBlockSequence(0x300a, 0x03a6);
+ Tag const IonControlPointSequence(0x300a, 0x03a8);
+ Tag const IonWedgeSequence(0x300a, 0x03aa);
+ Tag const IonWedgePositionSequence(0x300a, 0x03ac);
+ Tag const ReferencedSetupImageSequence(0x300a, 0x0401);
+ Tag const SetupImageComment(0x300a, 0x0402);
+ Tag const MotionSynchronizationSequence(0x300a, 0x0410);
+ Tag const ControlPointOrientation(0x300a, 0x0412);
+ Tag const GeneralAccessorySequence(0x300a, 0x0420);
+ Tag const GeneralAccessoryID(0x300a, 0x0421);
+ Tag const GeneralAccessoryDescription(0x300a, 0x0422);
+ Tag const GeneralAccessoryType(0x300a, 0x0423);
+ Tag const GeneralAccessoryNumber(0x300a, 0x0424);
+ Tag const SourceToGeneralAccessoryDistance(0x300a, 0x0425);
+ Tag const ApplicatorGeometrySequence(0x300a, 0x0431);
+ Tag const ApplicatorApertureShape(0x300a, 0x0432);
+ Tag const ApplicatorOpening(0x300a, 0x0433);
+ Tag const ApplicatorOpeningX(0x300a, 0x0434);
+ Tag const ApplicatorOpeningY(0x300a, 0x0435);
+ Tag const SourceToApplicatorMountingPositionDistance(0x300a, 0x0436);
+ Tag const NumberOfBlockSlabItems(0x300a, 0x0440);
+ Tag const BlockSlabSequence(0x300a, 0x0441);
+ Tag const BlockSlabThickness(0x300a, 0x0442);
+ Tag const BlockSlabNumber(0x300a, 0x0443);
+ Tag const DeviceMotionControlSequence(0x300a, 0x0450);
+ Tag const DeviceMotionExecutionMode(0x300a, 0x0451);
+ Tag const DeviceMotionObservationMode(0x300a, 0x0452);
+ Tag const DeviceMotionParameterCodeSequence(0x300a, 0x0453);
+ Tag const ReferencedRTPlanSequence(0x300c, 0x0002);
+ Tag const ReferencedBeamSequence(0x300c, 0x0004);
+ Tag const ReferencedBeamNumber(0x300c, 0x0006);
+ Tag const ReferencedReferenceImageNumber(0x300c, 0x0007);
+ Tag const StartCumulativeMetersetWeight(0x300c, 0x0008);
+ Tag const EndCumulativeMetersetWeight(0x300c, 0x0009);
+ Tag const ReferencedBrachyApplicationSetupSequence(0x300c, 0x000a);
+ Tag const ReferencedBrachyApplicationSetupNumber(0x300c, 0x000c);
+ Tag const ReferencedSourceNumber(0x300c, 0x000e);
+ Tag const ReferencedFractionGroupSequence(0x300c, 0x0020);
+ Tag const ReferencedFractionGroupNumber(0x300c, 0x0022);
+ Tag const ReferencedVerificationImageSequence(0x300c, 0x0040);
+ Tag const ReferencedReferenceImageSequence(0x300c, 0x0042);
+ Tag const ReferencedDoseReferenceSequence(0x300c, 0x0050);
+ Tag const ReferencedDoseReferenceNumber(0x300c, 0x0051);
+ Tag const BrachyReferencedDoseReferenceSequence(0x300c, 0x0055);
+ Tag const ReferencedStructureSetSequence(0x300c, 0x0060);
+ Tag const ReferencedPatientSetupNumber(0x300c, 0x006a);
+ Tag const ReferencedDoseSequence(0x300c, 0x0080);
+ Tag const ReferencedToleranceTableNumber(0x300c, 0x00a0);
+ Tag const ReferencedBolusSequence(0x300c, 0x00b0);
+ Tag const ReferencedWedgeNumber(0x300c, 0x00c0);
+ Tag const ReferencedCompensatorNumber(0x300c, 0x00d0);
+ Tag const ReferencedBlockNumber(0x300c, 0x00e0);
+ Tag const ReferencedControlPointIndex(0x300c, 0x00f0);
+ Tag const ReferencedControlPointSequence(0x300c, 0x00f2);
+ Tag const ReferencedStartControlPointIndex(0x300c, 0x00f4);
+ Tag const ReferencedStopControlPointIndex(0x300c, 0x00f6);
+ Tag const ReferencedRangeShifterNumber(0x300c, 0x0100);
+ Tag const ReferencedLateralSpreadingDeviceNumber(0x300c, 0x0102);
+ Tag const ReferencedRangeModulatorNumber(0x300c, 0x0104);
+ Tag const ApprovalStatus(0x300e, 0x0002);
+ Tag const ReviewDate(0x300e, 0x0004);
+ Tag const ReviewTime(0x300e, 0x0005);
+ Tag const ReviewerName(0x300e, 0x0008);
+ Tag const Arbitrary(0x4000, 0x0010);
+ Tag const TextComments(0x4000, 0x4000);
+ Tag const ResultsID(0x4008, 0x0040);
+ Tag const ResultsIDIssuer(0x4008, 0x0042);
+ Tag const ReferencedInterpretationSequence(0x4008, 0x0050);
+ Tag const ReportProductionStatusTrial(0x4008, 0x00ff);
+ Tag const InterpretationRecordedDate(0x4008, 0x0100);
+ Tag const InterpretationRecordedTime(0x4008, 0x0101);
+ Tag const InterpretationRecorder(0x4008, 0x0102);
+ Tag const ReferenceToRecordedSound(0x4008, 0x0103);
+ Tag const InterpretationTranscriptionDate(0x4008, 0x0108);
+ Tag const InterpretationTranscriptionTime(0x4008, 0x0109);
+ Tag const InterpretationTranscriber(0x4008, 0x010a);
+ Tag const InterpretationText(0x4008, 0x010b);
+ Tag const InterpretationAuthor(0x4008, 0x010c);
+ Tag const InterpretationApproverSequence(0x4008, 0x0111);
+ Tag const InterpretationApprovalDate(0x4008, 0x0112);
+ Tag const InterpretationApprovalTime(0x4008, 0x0113);
+ Tag const PhysicianApprovingInterpretation(0x4008, 0x0114);
+ Tag const InterpretationDiagnosisDescription(0x4008, 0x0115);
+ Tag const InterpretationDiagnosisCodeSequence(0x4008, 0x0117);
+ Tag const ResultsDistributionListSequence(0x4008, 0x0118);
+ Tag const DistributionName(0x4008, 0x0119);
+ Tag const DistributionAddress(0x4008, 0x011a);
+ Tag const InterpretationID(0x4008, 0x0200);
+ Tag const InterpretationIDIssuer(0x4008, 0x0202);
+ Tag const InterpretationTypeID(0x4008, 0x0210);
+ Tag const InterpretationStatusID(0x4008, 0x0212);
+ Tag const Impressions(0x4008, 0x0300);
+ Tag const ResultsComments(0x4008, 0x4000);
+ Tag const LowEnergyDetectors(0x4010, 0x0001);
+ Tag const HighEnergyDetectors(0x4010, 0x0002);
+ Tag const DetectorGeometrySequence(0x4010, 0x0004);
+ Tag const ThreatROIVoxelSequence(0x4010, 0x1001);
+ Tag const ThreatROIBase(0x4010, 0x1004);
+ Tag const ThreatROIExtents(0x4010, 0x1005);
+ Tag const ThreatROIBitmap(0x4010, 0x1006);
+ Tag const RouteSegmentID(0x4010, 0x1007);
+ Tag const GantryType(0x4010, 0x1008);
+ Tag const OOIOwnerType(0x4010, 0x1009);
+ Tag const RouteSegmentSequence(0x4010, 0x100a);
+ Tag const PotentialThreatObjectID(0x4010, 0x1010);
+ Tag const ThreatSequence(0x4010, 0x1011);
+ Tag const ThreatCategory(0x4010, 0x1012);
+ Tag const ThreatCategoryDescription(0x4010, 0x1013);
+ Tag const ATDAbilityAssessment(0x4010, 0x1014);
+ Tag const ATDAssessmentFlag(0x4010, 0x1015);
+ Tag const ATDAssessmentProbability(0x4010, 0x1016);
+ Tag const Mass(0x4010, 0x1017);
+ Tag const Density(0x4010, 0x1018);
+ Tag const ZEffective(0x4010, 0x1019);
+ Tag const BoardingPassID(0x4010, 0x101a);
+ Tag const CenterOfMass(0x4010, 0x101b);
+ Tag const CenterOfPTO(0x4010, 0x101c);
+ Tag const BoundingPolygon(0x4010, 0x101d);
+ Tag const RouteSegmentStartLocationID(0x4010, 0x101e);
+ Tag const RouteSegmentEndLocationID(0x4010, 0x101f);
+ Tag const RouteSegmentLocationIDType(0x4010, 0x1020);
+ Tag const AbortReason(0x4010, 0x1021);
+ Tag const VolumeOfPTO(0x4010, 0x1023);
+ Tag const AbortFlag(0x4010, 0x1024);
+ Tag const RouteSegmentStartTime(0x4010, 0x1025);
+ Tag const RouteSegmentEndTime(0x4010, 0x1026);
+ Tag const TDRType(0x4010, 0x1027);
+ Tag const InternationalRouteSegment(0x4010, 0x1028);
+ Tag const ThreatDetectionAlgorithmandVersion(0x4010, 0x1029);
+ Tag const AssignedLocation(0x4010, 0x102a);
+ Tag const AlarmDecisionTime(0x4010, 0x102b);
+ Tag const AlarmDecision(0x4010, 0x1031);
+ Tag const NumberOfTotalObjects(0x4010, 0x1033);
+ Tag const NumberOfAlarmObjects(0x4010, 0x1034);
+ Tag const PTORepresentationSequence(0x4010, 0x1037);
+ Tag const ATDAssessmentSequence(0x4010, 0x1038);
+ Tag const TIPType(0x4010, 0x1039);
+ Tag const DICOSVersion(0x4010, 0x103a);
+ Tag const OOIOwnerCreationTime(0x4010, 0x1041);
+ Tag const OOIType(0x4010, 0x1042);
+ Tag const OOISize(0x4010, 0x1043);
+ Tag const AcquisitionStatus(0x4010, 0x1044);
+ Tag const BasisMaterialsCodeSequence(0x4010, 0x1045);
+ Tag const PhantomType(0x4010, 0x1046);
+ Tag const OOIOwnerSequence(0x4010, 0x1047);
+ Tag const ScanType(0x4010, 0x1048);
+ Tag const ItineraryID(0x4010, 0x1051);
+ Tag const ItineraryIDType(0x4010, 0x1052);
+ Tag const ItineraryIDAssigningAuthority(0x4010, 0x1053);
+ Tag const RouteID(0x4010, 0x1054);
+ Tag const RouteIDAssigningAuthority(0x4010, 0x1055);
+ Tag const InboundArrivalType(0x4010, 0x1056);
+ Tag const CarrierID(0x4010, 0x1058);
+ Tag const CarrierIDAssigningAuthority(0x4010, 0x1059);
+ Tag const SourceOrientation(0x4010, 0x1060);
+ Tag const SourcePosition(0x4010, 0x1061);
+ Tag const BeltHeight(0x4010, 0x1062);
+ Tag const AlgorithmRoutingCodeSequence(0x4010, 0x1064);
+ Tag const TransportClassification(0x4010, 0x1067);
+ Tag const OOITypeDescriptor(0x4010, 0x1068);
+ Tag const TotalProcessingTime(0x4010, 0x1069);
+ Tag const DetectorCalibrationData(0x4010, 0x106c);
+ Tag const AdditionalScreeningPerformed(0x4010, 0x106d);
+ Tag const AdditionalInspectionSelectionCriteria(0x4010, 0x106e);
+ Tag const AdditionalInspectionMethodSequence(0x4010, 0x106f);
+ Tag const AITDeviceType(0x4010, 0x1070);
+ Tag const QRMeasurementsSequence(0x4010, 0x1071);
+ Tag const TargetMaterialSequence(0x4010, 0x1072);
+ Tag const SNRThreshold(0x4010, 0x1073);
+ Tag const ImageScaleRepresentation(0x4010, 0x1075);
+ Tag const ReferencedPTOSequence(0x4010, 0x1076);
+ Tag const ReferencedTDRInstanceSequence(0x4010, 0x1077);
+ Tag const PTOLocationDescription(0x4010, 0x1078);
+ Tag const AnomalyLocatorIndicatorSequence(0x4010, 0x1079);
+ Tag const AnomalyLocatorIndicator(0x4010, 0x107a);
+ Tag const PTORegionSequence(0x4010, 0x107b);
+ Tag const InspectionSelectionCriteria(0x4010, 0x107c);
+ Tag const SecondaryInspectionMethodSequence(0x4010, 0x107d);
+ Tag const PRCSToRCSOrientation(0x4010, 0x107e);
+ Tag const MACParametersSequence(0x4ffe, 0x0001);
+ Tag const SharedFunctionalGroupsSequence(0x5200, 0x9229);
+ Tag const PerFrameFunctionalGroupsSequence(0x5200, 0x9230);
+ Tag const WaveformSequence(0x5400, 0x0100);
+ Tag const ChannelMinimumValue(0x5400, 0x0110);
+ Tag const ChannelMaximumValue(0x5400, 0x0112);
+ Tag const WaveformBitsAllocated(0x5400, 0x1004);
+ Tag const WaveformSampleInterpretation(0x5400, 0x1006);
+ Tag const WaveformPaddingValue(0x5400, 0x100a);
+ Tag const WaveformData(0x5400, 0x1010);
+ Tag const FirstOrderPhaseCorrectionAngle(0x5600, 0x0010);
+ Tag const SpectroscopyData(0x5600, 0x0020);
+ Tag const FloatPixelData(0x7fe0, 0x0008);
+ Tag const DoubleFloatPixelData(0x7fe0, 0x0009);
+ Tag const PixelData(0x7fe0, 0x0010);
+ Tag const CoefficientsSDVN(0x7fe0, 0x0020);
+ Tag const CoefficientsSDHN(0x7fe0, 0x0030);
+ Tag const CoefficientsSDDN(0x7fe0, 0x0040);
+ Tag const DigitalSignaturesSequence(0xfffa, 0xfffa);
+ Tag const DataSetTrailingPadding(0xfffc, 0xfffc);
+ Tag const Item(0xfffe, 0xe000);
+ Tag const ItemDelimitationItem(0xfffe, 0xe00d);
+ Tag const SequenceDelimitationItem(0xfffe, 0xe0dd);
+}
+
+}
+
+#endif // _afc7b2d7_0869_4fea_9a9b_7fe6228baca9
diff --git a/src/dcmtkpp/unicode.cpp b/src/dcmtkpp/unicode.cpp
new file mode 100644
index 0000000..76246c7
--- /dev/null
+++ b/src/dcmtkpp/unicode.cpp
@@ -0,0 +1,332 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "dcmtkpp/unicode.h"
+
+#include <algorithm>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+
+#include <unicode/errorcode.h>
+#include <unicode/unistr.h>
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+std::map<std::string, std::string> const icu_encodings = {
+ { "", "" },
+ // Single-Byte Character Sets Without Code Extensions
+ { "ISO_IR 100", "iso-ir-100" },
+ { "ISO_IR 101", "iso-ir-101" },
+ { "ISO_IR 109", "iso-ir-109" },
+ { "ISO_IR 110", "iso-ir-110" },
+ { "ISO_IR 144", "iso-ir-144" },
+ { "ISO_IR 127", "iso-ir-127" },
+ { "ISO_IR 126", "iso-ir-126" },
+ { "ISO_IR 138", "iso-ir-138" },
+ { "ISO_IR 148", "iso-ir-148" },
+ { "ISO_IR 13", "Shift_JIS" }, // Since the 0x00 to 0x7f characters
+ // match ASCII (i.e. Romaji) and the 0xa1 to 0xdf map to half-width
+ // katakana of JIS X 0201. cf. https://en.wikipedia.org/wiki/Shift_JIS
+ { "ISO_IR 166", "TIS-620" },
+
+ // Single-Byte Character Sets with Code Extensions
+ { "ISO 2022 IR 6", "" },
+ { "ISO 2022 IR 100", "iso-ir-100" },
+ { "ISO 2022 IR 101", "iso-ir-101" },
+ { "ISO 2022 IR 109", "iso-ir-109" },
+ { "ISO 2022 IR 110", "iso-ir-110" },
+ { "ISO 2022 IR 144", "iso-ir-144" },
+ { "ISO 2022 IR 127", "iso-ir-127" },
+ { "ISO 2022 IR 126", "iso-ir-126" },
+ { "ISO 2022 IR 138", "iso-ir-138" },
+ { "ISO 2022 IR 148", "iso-ir-148" },
+ { "ISO 2022 IR 13", "Shift_JIS" },
+ { "ISO 2022 IR 166", "TIS-620" },
+
+ { "\x1B\x28\x42", "" },
+ { "\x1B\x2D\x41", "iso-ir-100" },
+ { "\x1B\x2D\x42", "iso-ir-101" },
+ { "\x1B\x2D\x43", "iso-ir-109" },
+ { "\x1B\x2D\x44", "iso-ir-110" },
+ { "\x1B\x2D\x4C", "iso-ir-144" },
+ { "\x1B\x2D\x47", "iso-ir-127" },
+ { "\x1B\x2D\x46", "iso-ir-126" },
+ { "\x1B\x2D\x48", "iso-ir-138" },
+ { "\x1B\x2D\x4D", "iso-ir-148" },
+ { "\x1B\x29\x49", "ISO-2022-JP" },
+ { "\x1B\x28\x4A", "ISO-2022-JP" },
+ { "\x1B\x2D\x54", "TIS-620" },
+
+ // Multi-Byte Character Sets with Code Extensions
+ { "ISO 2022 IR 87", "ISO-2022-JP" },
+ { "ISO 2022 IR 149", "EUC-KR" },
+ { "ISO 2022 IR 58", "ISO-2022-CN" },
+
+ { "\x1B\x24\x42", "ISO-2022-JP" },
+ { "\x1B\x24\x28\x44", "ISO-2022-JP" },
+ { "\x1B\x24\x29\x43", "iso-ir-149" },
+ { "\x1B\x24\x29\x41", "iso-ir-58" },
+
+ // Multi-Byte Character Sets Without Code Extensions
+ { "ISO_IR 192", "UTF-8" },
+ { "GB18030", "GB18030" },
+ // GBK
+};
+
+std::map<std::string, std::vector<std::string>> const escape_sequences = {
+ { "", { "\x1B\x28\x42" } },
+ { "ISO 2022 IR 6", { "\x1B\x28\x42" } },
+ { "ISO 2022 IR 100", { "\x1B\x2D\x41", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 101", { "\x1B\x2D\x42", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 109", { "\x1B\x2D\x43", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 110", { "\x1B\x2D\x44", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 144", { "\x1B\x2D\x4C", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 127", { "\x1B\x2D\x47", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 126", { "\x1B\x2D\x46", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 138", { "\x1B\x2D\x48", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 148", { "\x1B\x2D\x4D", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 13", { "\x1B\x29\x49", "\x1B\x28\x4A" } },
+ { "ISO 2022 IR 166", { "\x1B\x2D\x54", "\x1B\x28\x42" } },
+
+ { "ISO 2022 IR 87", { "\x1B\x24\x42", "\x1B\x28\x42" } },
+ { "ISO 2022 IR 159", { "\x1B\x24\x28\x44" } },
+ { "ISO 2022 IR 149", { "\x1B\x24\x29\x43" } },
+ { "ISO 2022 IR 58", { "\x1B\x24\x29\x41" } },
+};
+
+std::string find_encoder(std::string const & specific_character_set)
+{
+ std::string encoder;
+ auto const it = icu_encodings.find(specific_character_set);
+ if(it == icu_encodings.end())
+ {
+ throw Exception("Unknown encoding: "+specific_character_set);
+ }
+ encoder = it->second;
+
+ return encoder;
+}
+
+std::string as_utf8(
+ std::string::const_iterator const begin, std::string::const_iterator const end,
+ std::string const & encoding)
+{
+ icu::UnicodeString unicode(&(*begin), end-begin, encoding.c_str());
+ std::string result;
+ unicode.toUTF8String(result);
+
+ return result;
+}
+
+std::string as_utf8(
+ std::string::const_iterator const begin, std::string::const_iterator const end,
+ std::string const & initial_encoder,
+ std::vector<std::string> const & active_escape_sequences)
+{
+ std::string encoded;
+
+ auto encoder = initial_encoder;
+
+ auto item_begin = begin;
+ while(item_begin != end)
+ {
+ auto const item_end = std::find(item_begin+1, end, '\x1B');
+
+ if(*item_begin == '\x1B')
+ {
+ std::string escape_sequence(item_begin, item_begin+3);
+
+ // Find an encoder for the escape sequence
+ if(
+ std::find(
+ active_escape_sequences.begin(), active_escape_sequences.end(),
+ escape_sequence) != active_escape_sequences.end())
+ {
+ encoder = find_encoder(escape_sequence);
+ }
+ else
+ {
+ escape_sequence += *(item_begin+3);
+ if(
+ std::find(
+ active_escape_sequences.begin(), active_escape_sequences.end(),
+ escape_sequence) != active_escape_sequences.end())
+ {
+ encoder = find_encoder(escape_sequence);
+ }
+ else
+ {
+ // Unknown escape sequence: do not update the encoder,
+ // hope for the best.
+ }
+ }
+
+ if(encoder != "ISO-2022-JP")
+ {
+ // The ISO-2022-JP encoder of ICU must have the escape
+ // sequences
+ item_begin += escape_sequence.size();
+ }
+ }
+
+ encoded += as_utf8(item_begin, item_end, encoder);
+
+ item_begin = item_end;
+ }
+
+ return encoded;
+}
+
+enum class Group
+{
+ Alphabetic,
+ Ideographic,
+ Phonetic
+};
+
+std::vector<std::string> get_active_escape_sequences(
+ Value::Strings const & specific_character_set, Group const & group)
+{
+ std::vector<std::string> active_escape_sequences;
+
+ if(specific_character_set.size() >= 2)
+ {
+ auto const escape_sequences_it = escape_sequences.find(specific_character_set[1]);
+ if(escape_sequences_it == escape_sequences.end())
+ {
+ throw Exception("Unknown specific character set: "+specific_character_set[1]);
+ }
+ std::copy(
+ escape_sequences_it->second.begin(),
+ escape_sequences_it->second.end(),
+ std::back_inserter(active_escape_sequences));
+ }
+ if(group == Group::Phonetic)
+ {
+ auto const escape_sequences_it = escape_sequences.find(specific_character_set[0]);
+ if(escape_sequences_it != escape_sequences.end())
+ {
+ std::copy(
+ escape_sequences_it->second.begin(),
+ escape_sequences_it->second.end(),
+ std::back_inserter(active_escape_sequences));
+ }
+ if(specific_character_set.size() >= 3)
+ {
+ auto const escape_sequences_it = escape_sequences.find(specific_character_set[2]);
+ if(escape_sequences_it == escape_sequences.end())
+ {
+ throw Exception("Unknown specific character set: "+specific_character_set[2]);
+ }
+ std::copy(
+ escape_sequences_it->second.begin(),
+ escape_sequences_it->second.end(),
+ std::back_inserter(active_escape_sequences));
+ }
+ }
+
+ return active_escape_sequences;
+}
+
+std::string as_utf8(
+ std::string const & input, Value::Strings const & specific_character_set,
+ bool is_pn)
+{
+ // Control characters: line feed, carriage return, form feed and tabulation
+ // For Person Name, add the group splitters
+ std::string splitters = "\n\r\f\t";
+ if(is_pn)
+ {
+ if(
+ std::find(
+ specific_character_set.begin(), specific_character_set.end(),
+ "ISO 2022 IR 13") != specific_character_set.end() ||
+ std::find(
+ specific_character_set.begin(), specific_character_set.end(),
+ "ISO 2022 IR 87") != specific_character_set.end())
+ {
+ // The ISO-2022-JP encoder of ICU is stateful, whereas all other
+ // ISO 2022 encoders seem to be only codepages (i.e. stateless)
+ splitters.append("=");
+ }
+ else
+ {
+ splitters.append("^=");
+ }
+ }
+
+ std::string result;
+
+ Group group=Group::Alphabetic;
+
+ auto begin = input.begin();
+ while(begin != input.end())
+ {
+ // Active character set resets to default before any of the splitters
+ // cf. PS 3.5, 6.1.2.5.3
+ auto const end = std::find_first_of(
+ begin, input.end(), splitters.begin(), splitters.end());
+
+ std::string encoded;
+
+ if(specific_character_set.empty())
+ {
+ encoded = std::string(begin, end);
+ }
+ else if(is_pn && group != Group::Alphabetic)
+ {
+ auto const initial_encoder = find_encoder(specific_character_set[0]);
+ auto const active_escape_sequences =
+ get_active_escape_sequences(specific_character_set, group);
+ encoded = as_utf8(begin, end, initial_encoder, active_escape_sequences);
+ }
+ else
+ {
+ auto const encoder = find_encoder(specific_character_set[0]);
+ encoded = as_utf8(begin, end, encoder);
+ }
+
+ result.append(encoded);
+
+ // If present, add the splitter to the UTF-8 string.
+ if(end != input.end())
+ {
+ result.push_back(*end);
+ begin = end+1;
+ if(is_pn && *end == '=')
+ {
+ if(group == Group::Alphabetic)
+ {
+ group = Group::Ideographic;
+ }
+ else if(group == Group::Ideographic)
+ {
+ group = Group::Phonetic;
+ }
+ else
+ {
+ throw Exception("Too many groups");
+ }
+ }
+ }
+ else
+ {
+ begin = end;
+ }
+ }
+
+ return result;
+}
+
+}
diff --git a/src/dcmtkpp/unicode.h b/src/dcmtkpp/unicode.h
new file mode 100644
index 0000000..4815d80
--- /dev/null
+++ b/src/dcmtkpp/unicode.h
@@ -0,0 +1,25 @@
+/*************************************************************************
+ * dcmtkpp - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _4a178325_e3d6_4f6f_9a18_ba6a983ee396
+#define _4a178325_e3d6_4f6f_9a18_ba6a983ee396
+
+#include <string>
+#include "dcmtkpp/Value.h"
+
+namespace dcmtkpp
+{
+
+/// @brief Convert a string to its UTF-8 representation
+std::string as_utf8(
+ std::string const & input, Value::Strings const & specific_character_set,
+ bool is_pn=false);
+
+}
+
+#endif // _4a178325_e3d6_4f6f_9a18_ba6a983ee396
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..a8fe9a3
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,41 @@
+find_package(Boost COMPONENTS unit_test_framework REQUIRED)
+link_directories(${Boost_LIBRARY_DIRS})
+add_definitions(-DBOOST_TEST_DYN_LINK)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src)
+
+add_definitions("-D HAVE_CONFIG_H")
+
+file(GLOB_RECURSE tests *.cpp)
+foreach(test_file ${tests})
+ get_filename_component(test ${test_file} NAME_WE)
+ add_executable(${test} ${test_file})
+ target_link_libraries(${test} dcmtkpp ${Boost_LIBRARIES})
+ file(READ ${test_file} content)
+
+ set(pattern "BOOST_(AUTO|FIXTURE)_TEST_CASE\\(([^),]+)")
+
+ string(REGEX MATCHALL ${pattern} cases ${content})
+
+ foreach(case ${cases})
+ string(REGEX REPLACE ${pattern} "\\2" case ${case})
+ if(NOT ${case} MATCHES "##")
+ add_test("${test}_${case}" "${test}" "--run_test=${case}")
+ endif()
+ endforeach()
+
+ set(pattern "ElementTest\\([\n ]+([A-Z]+)")
+
+ string(REGEX MATCHALL ${pattern} matches ${content})
+
+ foreach(match ${matches})
+ string(REGEX REPLACE ${pattern} "\\1" vr ${match})
+
+ set(case "${vr}FromDcmtkpp")
+ add_test("${test}_${case}" "${test}" "--run_test=${case}")
+
+ set(case "${vr}ToDcmtkpp")
+ add_test("${test}_${case}" "${test}" "--run_test=${case}")
+ endforeach()
+
+endforeach()
diff --git a/tests/MessageFixtureBase.h b/tests/MessageFixtureBase.h
new file mode 100644
index 0000000..55abb73
--- /dev/null
+++ b/tests/MessageFixtureBase.h
@@ -0,0 +1,54 @@
+#ifndef _779c46d6_b6ea_443a_9642_f1ec5b87d4b3
+#define _779c46d6_b6ea_443a_9642_f1ec5b87d4b3
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Message.h"
+
+/// @brief Base class for fixtures of Message-derived classes.
+template<typename TMessage>
+struct MessageFixtureBase
+{
+ /// @brief Check that a specific message can be constructed from a generic Message.
+ void check_message_constructor(
+ dcmtkpp::DataSet const & command_set)
+ {
+ dcmtkpp::Message const generic_message(command_set);
+ TMessage const message(generic_message);
+ this->check(message);
+ }
+
+ /// @brief Check that a specific message can be constructed from a generic Message.
+ void check_message_constructor(
+ dcmtkpp::DataSet const & command_set, dcmtkpp::DataSet const & data_set)
+ {
+ dcmtkpp::Message const generic_message(command_set, data_set);
+ TMessage const message(generic_message);
+ this->check(message);
+ }
+
+ /// @brief Check that a specific message cannot be constructed from a generic Message.
+ void check_message_constructor_throw(
+ dcmtkpp::DataSet const & command_set)
+ {
+ dcmtkpp::Message const generic_message(command_set);
+ BOOST_CHECK_THROW(
+ TMessage const message(generic_message),
+ dcmtkpp::Exception);
+ }
+
+ /// @brief Check that a specific message cannot be constructed from a generic Message.
+ void check_message_constructor_throw(
+ dcmtkpp::DataSet const & command_set, dcmtkpp::DataSet const & data_set)
+ {
+ dcmtkpp::Message const generic_message(command_set, data_set);
+ BOOST_CHECK_THROW(
+ TMessage const message(generic_message),
+ dcmtkpp::Exception);
+ }
+
+ /// @brief Check that the specific message attributes are set correctly
+ virtual void check(TMessage const & message) =0;
+};
+
+#endif // _779c46d6_b6ea_443a_9642_f1ec5b87d4b3
diff --git a/tests/PeerFixtureBase.h b/tests/PeerFixtureBase.h
new file mode 100644
index 0000000..532501c
--- /dev/null
+++ b/tests/PeerFixtureBase.h
@@ -0,0 +1,86 @@
+#ifndef _b21e8d37_0125_4d64_84aa_f91d9d96612b
+#define _b21e8d37_0125_4d64_84aa_f91d9d96612b
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include "dcmtkpp/Association.h"
+#include "dcmtkpp/Network.h"
+
+/// @brief Base class for fixtures of requiring a working association.
+class PeerFixtureBase
+{
+public:
+ dcmtkpp::Network network;
+ dcmtkpp::Association association;
+
+ struct PresentationContext
+ {
+ std::string abstract_syntax;
+ std::vector<std::string> transfer_syntaxes;
+ T_ASC_SC_ROLE role;
+
+ PresentationContext(std::string const & abstract_syntax, std::vector<std::string> const & transfer_syntaxes, T_ASC_SC_ROLE role=ASC_SC_ROLE_DEFAULT)
+ : abstract_syntax(abstract_syntax),
+ transfer_syntaxes(transfer_syntaxes), role(role)
+ {
+ // Nothing else
+ }
+ };
+
+ PeerFixtureBase(T_ASC_NetworkRole role, int port, int timeout,
+ std::vector<PresentationContext> const & presentation_contexts)
+ : network(role, port, timeout), association()
+ {
+ this->network.initialize();
+
+ this->association.set_own_ae_title(
+ this->_get_environment_variable("DCMTKPP_OWN_AET"));
+ this->association.set_peer_host_name(
+ this->_get_environment_variable("DCMTKPP_PEER_HOST_NAME"));
+ this->association.set_peer_port(
+ this->_get_environment_variable<uint16_t>("DCMTKPP_PEER_PORT"));
+ this->association.set_peer_ae_title(
+ this->_get_environment_variable("DCMTKPP_PEER_AET"));
+ for(auto const & presentation_context: presentation_contexts)
+ {
+ this->association.add_presentation_context(
+ presentation_context.abstract_syntax,
+ presentation_context.transfer_syntaxes,
+ presentation_context.role);
+ }
+
+ this->association.associate(this->network);
+ }
+
+ ~PeerFixtureBase()
+ {
+ this->association.release();
+ this->network.drop();
+ }
+
+private:
+
+ std::string _get_environment_variable(std::string const & name) const
+ {
+ char* value = getenv(name.c_str());
+ if(value == NULL)
+ {
+ BOOST_FAIL(name + " is not defined");
+ }
+ return value;
+ }
+
+ template<typename T>
+ T _get_environment_variable(std::string const & name) const
+ {
+ return boost::lexical_cast<T>(this->_get_environment_variable(name));
+ }
+};
+
+#endif // _b21e8d37_0125_4d64_84aa_f91d9d96612b
diff --git a/tests/code/Association.cpp b/tests/code/Association.cpp
new file mode 100644
index 0000000..a300c2f
--- /dev/null
+++ b/tests/code/Association.cpp
@@ -0,0 +1,251 @@
+#define BOOST_TEST_MODULE Association
+#include <boost/test/unit_test.hpp>
+
+#include <ostream>
+
+#include "dcmtkpp/Association.h"
+#include "dcmtkpp/Exception.h"
+
+#include "../PeerFixtureBase.h"
+
+namespace dcmtkpp
+{
+
+std::ostream & operator<<(std::ostream & stream, UserIdentityType const & type)
+{
+ stream << int(type);
+ return stream;
+}
+
+}
+
+BOOST_AUTO_TEST_CASE(DefaultConstructor)
+{
+ dcmtkpp::Association association;
+ BOOST_CHECK_EQUAL(association.get_own_ae_title(), "");
+
+ BOOST_CHECK_EQUAL(association.get_peer_host_name(), "");
+ BOOST_CHECK_EQUAL(association.get_peer_port(), 104);
+ BOOST_CHECK_EQUAL(association.get_peer_ae_title(), "");
+
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_type(), dcmtkpp::UserIdentityType::None);
+ BOOST_CHECK_EQUAL(association.get_user_identity_primary_field(), "");
+ BOOST_CHECK_EQUAL(association.get_user_identity_secondary_field(), "");
+
+ BOOST_CHECK(!association.is_associated());
+ BOOST_CHECK_EQUAL(
+ association.get_association(), static_cast<T_ASC_Association*>(NULL));
+}
+
+BOOST_AUTO_TEST_CASE(CopyConstructor)
+{
+ dcmtkpp::Association association;
+ association.set_own_ae_title("local");
+
+ association.set_peer_host_name("pacs.example.com");
+ association.set_peer_port(11112);
+ association.set_peer_ae_title("remote");
+
+ association.set_user_identity_to_username_and_password("foo", "bar");
+
+ dcmtkpp::Association const other(association);
+
+ BOOST_CHECK_EQUAL(other.get_own_ae_title(), association.get_own_ae_title());
+
+ BOOST_CHECK_EQUAL(
+ other.get_peer_host_name(), association.get_peer_host_name());
+ BOOST_CHECK_EQUAL(other.get_peer_port(), association.get_peer_port());
+ BOOST_CHECK_EQUAL(
+ other.get_peer_ae_title(), association.get_peer_ae_title());
+
+ BOOST_CHECK_EQUAL(
+ other.get_user_identity_type(), association.get_user_identity_type());
+ BOOST_CHECK_EQUAL(
+ other.get_user_identity_primary_field(),
+ association.get_user_identity_primary_field());
+ BOOST_CHECK_EQUAL(
+ other.get_user_identity_secondary_field(),
+ association.get_user_identity_secondary_field());
+}
+
+BOOST_AUTO_TEST_CASE(Assignment)
+{
+ dcmtkpp::Association association;
+ association.set_own_ae_title("local");
+
+ association.set_peer_host_name("pacs.example.com");
+ association.set_peer_port(11112);
+ association.set_peer_ae_title("remote");
+
+ association.set_user_identity_to_username_and_password("foo", "bar");
+
+ dcmtkpp::Association other;
+ other = association;
+
+ BOOST_CHECK_EQUAL(other.get_own_ae_title(), association.get_own_ae_title());
+
+ BOOST_CHECK_EQUAL(
+ other.get_peer_host_name(), association.get_peer_host_name());
+ BOOST_CHECK_EQUAL(other.get_peer_port(), association.get_peer_port());
+ BOOST_CHECK_EQUAL(
+ other.get_peer_ae_title(), association.get_peer_ae_title());
+
+ BOOST_CHECK_EQUAL(
+ other.get_user_identity_type(), association.get_user_identity_type());
+ BOOST_CHECK_EQUAL(
+ other.get_user_identity_primary_field(),
+ association.get_user_identity_primary_field());
+ BOOST_CHECK_EQUAL(
+ other.get_user_identity_secondary_field(),
+ association.get_user_identity_secondary_field());
+}
+
+BOOST_AUTO_TEST_CASE(OwnAETitle)
+{
+ dcmtkpp::Association association;
+ association.set_own_ae_title("myself");
+ BOOST_CHECK_EQUAL(association.get_own_ae_title(), "myself");
+}
+
+BOOST_AUTO_TEST_CASE(PeerHostName)
+{
+ dcmtkpp::Association association;
+ association.set_peer_host_name("pacs.example.com");
+ BOOST_CHECK_EQUAL(association.get_peer_host_name(), "pacs.example.com");
+}
+
+BOOST_AUTO_TEST_CASE(PeerPort)
+{
+ dcmtkpp::Association association;
+ association.set_peer_port(11112);
+ BOOST_CHECK_EQUAL(association.get_peer_port(), 11112);
+}
+
+BOOST_AUTO_TEST_CASE(PeerAETitle)
+{
+ dcmtkpp::Association association;
+ association.set_peer_ae_title("remote");
+ BOOST_CHECK_EQUAL(association.get_peer_ae_title(), "remote");
+}
+
+BOOST_AUTO_TEST_CASE(UserIdentityType)
+{
+ dcmtkpp::Association association;
+ association.set_user_identity_type(dcmtkpp::UserIdentityType::Username);
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_type(),
+ dcmtkpp::UserIdentityType::Username);
+}
+
+BOOST_AUTO_TEST_CASE(UserIdentityPrimaryField)
+{
+ dcmtkpp::Association association;
+ association.set_user_identity_primary_field("user");
+ BOOST_CHECK_EQUAL(association.get_user_identity_primary_field(), "user");
+}
+
+BOOST_AUTO_TEST_CASE(UserIdentitySecondaryField)
+{
+ dcmtkpp::Association association;
+ association.set_user_identity_secondary_field("password");
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_secondary_field(), "password");
+}
+
+BOOST_AUTO_TEST_CASE(UserIdentityNone)
+{
+ dcmtkpp::Association association;
+ association.set_user_identity_to_none();
+ BOOST_CHECK_EQUAL(association.get_user_identity_primary_field(), "");
+ BOOST_CHECK_EQUAL(association.get_user_identity_secondary_field(), "");
+}
+
+BOOST_AUTO_TEST_CASE(UserIdentityUsername)
+{
+ dcmtkpp::Association association;
+ association.set_user_identity_to_username("user");
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_type(),
+ dcmtkpp::UserIdentityType::Username);
+ BOOST_CHECK_EQUAL(association.get_user_identity_primary_field(), "user");
+ BOOST_CHECK_EQUAL(association.get_user_identity_secondary_field(), "");
+}
+
+BOOST_AUTO_TEST_CASE(UserIdentityUsernameAndPassword)
+{
+ dcmtkpp::Association association;
+ association.set_user_identity_to_username_and_password("user", "password");
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_type(),
+ dcmtkpp::UserIdentityType::UsernameAndPassword);
+ BOOST_CHECK_EQUAL(association.get_user_identity_primary_field(), "user");
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_secondary_field(), "password");
+}
+
+BOOST_AUTO_TEST_CASE(UserIdentityKerberos)
+{
+ dcmtkpp::Association association;
+ association.set_user_identity_to_kerberos("ticket");
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_type(),
+ dcmtkpp::UserIdentityType::Kerberos);
+ BOOST_CHECK_EQUAL(association.get_user_identity_primary_field(), "ticket");
+ BOOST_CHECK_EQUAL(association.get_user_identity_secondary_field(), "");
+}
+
+BOOST_AUTO_TEST_CASE(UserIdentitySAML)
+{
+ dcmtkpp::Association association;
+ association.set_user_identity_to_saml("assertion");
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_type(), dcmtkpp::UserIdentityType::SAML);
+ BOOST_CHECK_EQUAL(
+ association.get_user_identity_primary_field(), "assertion");
+ BOOST_CHECK_EQUAL(association.get_user_identity_secondary_field(), "");
+}
+
+BOOST_AUTO_TEST_CASE(Associate)
+{
+ PeerFixtureBase fixture(NET_REQUESTOR, 0, 10,
+ {
+ { UID_VerificationSOPClass,
+ {UID_LittleEndianImplicitTransferSyntax}
+ }
+ });
+ BOOST_CHECK_THROW(
+ fixture.association.set_own_ae_title("foo"), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(
+ fixture.association.set_peer_host_name("foo"), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(
+ fixture.association.set_peer_port(1234), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(
+ fixture.association.set_peer_ae_title("foo"), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(
+ fixture.association.add_presentation_context(
+ UID_GETPatientRootQueryRetrieveInformationModel,
+ { UID_LittleEndianImplicitTransferSyntax }),
+ dcmtkpp::Exception);
+ BOOST_CHECK_THROW(
+ fixture.association.set_user_identity_type(dcmtkpp::UserIdentityType::SAML),
+ dcmtkpp::Exception);
+ BOOST_CHECK_THROW(
+ fixture.association.set_user_identity_primary_field("foo"),
+ dcmtkpp::Exception);
+ BOOST_CHECK_THROW(
+ fixture.association.set_user_identity_secondary_field("foo"),
+ dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Release)
+{
+ dcmtkpp::Association association;
+ BOOST_CHECK_THROW(association.release(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Abort)
+{
+ dcmtkpp::Association association;
+ BOOST_CHECK_THROW(association.abort(), dcmtkpp::Exception);
+}
diff --git a/tests/code/CEchoRequest.cpp b/tests/code/CEchoRequest.cpp
new file mode 100644
index 0000000..934a900
--- /dev/null
+++ b/tests/code/CEchoRequest.cpp
@@ -0,0 +1,56 @@
+#define BOOST_TEST_MODULE CEchoRequest
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CEchoRequest.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CEchoRequest>
+{
+ dcmtkpp::DataSet command_set;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_ECHO_RQ});
+ this->command_set.add("MessageID", {1234});
+ this->command_set.add("AffectedSOPClassUID", {UID_VerificationSOPClass});
+ }
+
+ void check(dcmtkpp::CEchoRequest const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_ECHO_RQ);
+ BOOST_CHECK_EQUAL(message.get_message_id(), 1234);
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(), UID_VerificationSOPClass);
+ BOOST_CHECK(!message.has_data_set());
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CEchoRequest const message(1234, UID_VerificationSOPClass);
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RSP};
+ this->check_message_constructor_throw(this->command_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingAffectSOPClass, Fixture)
+{
+ this->command_set.remove("AffectedSOPClassUID");
+ this->check_message_constructor_throw(this->command_set);
+}
diff --git a/tests/code/CEchoResponse.cpp b/tests/code/CEchoResponse.cpp
new file mode 100644
index 0000000..01195c4
--- /dev/null
+++ b/tests/code/CEchoResponse.cpp
@@ -0,0 +1,58 @@
+#define BOOST_TEST_MODULE CEchoResponse
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CEchoResponse.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CEchoResponse>
+{
+ dcmtkpp::DataSet command_set;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_ECHO_RSP});
+ this->command_set.add("MessageIDBeingRespondedTo", {1234});
+ this->command_set.add("Status", {STATUS_Success});
+ this->command_set.add("AffectedSOPClassUID", {UID_VerificationSOPClass});
+ }
+
+ void check(dcmtkpp::CEchoResponse const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_ECHO_RSP);
+ BOOST_CHECK_EQUAL(message.get_message_id_being_responded_to(), 1234);
+ BOOST_CHECK_EQUAL(message.get_status(), STATUS_Success);
+ BOOST_CHECK_EQUAL(message.get_affected_sop_class_uid(), UID_VerificationSOPClass);
+ BOOST_CHECK(!message.has_data_set());
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CEchoResponse const message(
+ 1234, STATUS_Success, UID_VerificationSOPClass);
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RQ};
+ this->check_message_constructor_throw(this->command_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingAffectSOPClass, Fixture)
+{
+ this->command_set.remove("AffectedSOPClassUID");
+ this->check_message_constructor_throw(this->command_set);
+}
diff --git a/tests/code/CFindRequest.cpp b/tests/code/CFindRequest.cpp
new file mode 100644
index 0000000..f06ad39
--- /dev/null
+++ b/tests/code/CFindRequest.cpp
@@ -0,0 +1,83 @@
+#define BOOST_TEST_MODULE CFindRequest
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CFindRequest.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CFindRequest>
+{
+ dcmtkpp::DataSet command_set;
+ dcmtkpp::DataSet query;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_FIND_RQ});
+ this->command_set.add("MessageID", {1234});
+ this->command_set.add("AffectedSOPClassUID",
+ {UID_FINDPatientRootQueryRetrieveInformationModel});
+ this->command_set.add("Priority", {DIMSE_PRIORITY_MEDIUM});
+
+ this->query.add("PatientName", {"Doe^John"});
+ this->query.add("StudyDescription", {"Brain"});
+ this->query.add("QueryRetrieveLevel", {"STUDY"});
+ }
+
+ virtual void check(dcmtkpp::CFindRequest const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_FIND_RQ);
+ BOOST_CHECK_EQUAL(message.get_message_id(), 1234);
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(),
+ UID_FINDPatientRootQueryRetrieveInformationModel);
+ BOOST_CHECK(message.get_data_set() == this->query);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CFindRequest const message(
+ 1234, UID_FINDPatientRootQueryRetrieveInformationModel,
+ DIMSE_PRIORITY_MEDIUM, this->query);
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RQ};
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingAffectSOPClass, Fixture)
+{
+ this->command_set.remove("AffectedSOPClassUID");
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingPriority, Fixture)
+{
+ this->command_set.remove("Priority");
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingQuery, Fixture)
+{
+ this->check_message_constructor_throw(this->command_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorEmptyQuery, Fixture)
+{
+ dcmtkpp::DataSet empty;
+ this->check_message_constructor_throw(this->command_set, empty);
+}
diff --git a/tests/code/CFindResponse.cpp b/tests/code/CFindResponse.cpp
new file mode 100644
index 0000000..55a17e9
--- /dev/null
+++ b/tests/code/CFindResponse.cpp
@@ -0,0 +1,72 @@
+#define BOOST_TEST_MODULE CFindResponse
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CFindResponse.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CFindResponse>
+{
+ dcmtkpp::DataSet command_set;
+ dcmtkpp::DataSet data_set;
+
+ Fixture()
+ {
+ command_set.add("CommandField", {dcmtkpp::Message::Command::C_FIND_RSP});
+ command_set.add("MessageIDBeingRespondedTo", {1234});
+ command_set.add("Status", {STATUS_Success});
+
+ command_set.add("MessageID", {5678});
+ command_set.add("AffectedSOPClassUID",
+ {UID_FINDStudyRootQueryRetrieveInformationModel});
+
+ data_set.add("PatientName", {"Doe^John"});
+ data_set.add("PatientID", {"DJ123"});
+ data_set.add("StudyDescription", {"Brain"});
+ data_set.add("StudyInstanceUID", {"1.2.3"});
+ }
+
+ virtual void check(dcmtkpp::CFindResponse const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_FIND_RSP);
+ BOOST_CHECK_EQUAL(message.get_message_id_being_responded_to(), 1234);
+ BOOST_CHECK_EQUAL(message.get_status(), STATUS_Success);
+
+ BOOST_CHECK(message.has_message_id());
+ BOOST_CHECK_EQUAL(message.get_message_id(), 5678);
+
+ BOOST_CHECK(message.has_affected_sop_class_uid());
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(),
+ UID_FINDStudyRootQueryRetrieveInformationModel);
+
+ BOOST_CHECK(message.has_data_set());
+ BOOST_CHECK(message.get_data_set() == this->data_set);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CFindResponse message(1234, STATUS_Success, this->data_set);
+ message.set_message_id(5678);
+ message.set_affected_sop_class_uid(
+ UID_FINDStudyRootQueryRetrieveInformationModel);
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set, this->data_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RQ};
+ this->check_message_constructor_throw(this->command_set, this->data_set);
+}
diff --git a/tests/code/CGetRequest.cpp b/tests/code/CGetRequest.cpp
new file mode 100644
index 0000000..7a83ace
--- /dev/null
+++ b/tests/code/CGetRequest.cpp
@@ -0,0 +1,80 @@
+#define BOOST_TEST_MODULE CGetRequest
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CGetRequest.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/registry.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CGetRequest>
+{
+ dcmtkpp::DataSet command_set;
+ dcmtkpp::DataSet query;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_GET_RQ});
+ this->command_set.add("MessageID", {1234});
+ this->command_set.add("AffectedSOPClassUID",
+ {UID_GETPatientRootQueryRetrieveInformationModel});
+ this->command_set.add("Priority", {DIMSE_PRIORITY_MEDIUM});
+
+ this->query.add("PatientName", {"Doe^John"});
+ this->query.add("StudyDescription", {"Brain"});
+ this->query.add("QueryRetrieveLevel", {"STUDY"});
+ }
+
+ virtual void check(dcmtkpp::CGetRequest const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_GET_RQ);
+ BOOST_CHECK_EQUAL(message.get_message_id(), 1234);
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(),
+ UID_GETPatientRootQueryRetrieveInformationModel);
+ BOOST_CHECK(message.has_data_set());
+ BOOST_CHECK(message.get_data_set() == this->query);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CGetRequest const message(
+ 1234, UID_GETPatientRootQueryRetrieveInformationModel,
+ DIMSE_PRIORITY_MEDIUM, this->query);
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RQ};
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingAffectSOPClass, Fixture)
+{
+ this->command_set.remove("AffectedSOPClassUID");
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingPriority, Fixture)
+{
+ this->command_set.remove("Priority");
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorEmptyQuery, Fixture)
+{
+ dcmtkpp::DataSet empty;
+ this->check_message_constructor_throw(this->command_set, empty);
+}
diff --git a/tests/code/CGetResponse.cpp b/tests/code/CGetResponse.cpp
new file mode 100644
index 0000000..c207421
--- /dev/null
+++ b/tests/code/CGetResponse.cpp
@@ -0,0 +1,94 @@
+#define BOOST_TEST_MODULE CGetResponse
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CGetResponse.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/registry.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CGetResponse>
+{
+ dcmtkpp::DataSet command_set;
+ dcmtkpp::DataSet data_set;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_GET_RSP});
+ this->command_set.add("MessageIDBeingRespondedTo", {1234});
+ this->command_set.add("Status", {STATUS_Success});
+
+ this->command_set.add("MessageID", {5678});
+ this->command_set.add("AffectedSOPClassUID",
+ {UID_GETStudyRootQueryRetrieveInformationModel});
+ this->command_set.add(dcmtkpp::registry::NumberOfRemainingSuboperations, {1});
+ this->command_set.add(dcmtkpp::registry::NumberOfCompletedSuboperations, {2});
+ this->command_set.add(dcmtkpp::registry::NumberOfFailedSuboperations, {3});
+ this->command_set.add(dcmtkpp::registry::NumberOfWarningSuboperations, {4});
+
+ this->data_set.add("PatientName", {"Doe^John"});
+ this->data_set.add("PatientID", {"DJ123"});
+ this->data_set.add("StudyDescription", {"Brain"});
+ this->data_set.add("StudyInstanceUID", {"1.2.3"});
+ }
+
+ virtual void check(dcmtkpp::CGetResponse const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_GET_RSP);
+ BOOST_CHECK_EQUAL(message.get_message_id_being_responded_to(), 1234);
+ BOOST_CHECK_EQUAL(message.get_status(), STATUS_Success);
+
+ BOOST_CHECK(message.has_message_id());
+ BOOST_CHECK_EQUAL(message.get_message_id(), 5678);
+
+ BOOST_CHECK(message.has_affected_sop_class_uid());
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(),
+ UID_GETStudyRootQueryRetrieveInformationModel);
+
+ BOOST_CHECK(message.has_number_of_remaining_sub_operations());
+ BOOST_CHECK_EQUAL(message.get_number_of_remaining_sub_operations(), 1);
+
+ BOOST_CHECK(message.has_number_of_completed_sub_operations());
+ BOOST_CHECK_EQUAL(message.get_number_of_completed_sub_operations(), 2);
+
+ BOOST_CHECK(message.has_number_of_failed_sub_operations());
+ BOOST_CHECK_EQUAL(message.get_number_of_failed_sub_operations(), 3);
+
+ BOOST_CHECK(message.has_number_of_warning_sub_operations());
+ BOOST_CHECK_EQUAL(message.get_number_of_warning_sub_operations(), 4);
+
+ BOOST_CHECK(message.has_data_set());
+ BOOST_CHECK(message.get_data_set() == this->data_set);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CGetResponse message(1234, STATUS_Success, this->data_set);
+ message.set_message_id(5678);
+ message.set_affected_sop_class_uid(
+ UID_GETStudyRootQueryRetrieveInformationModel);
+ message.set_number_of_remaining_sub_operations(1);
+ message.set_number_of_completed_sub_operations(2);
+ message.set_number_of_failed_sub_operations(3);
+ message.set_number_of_warning_sub_operations(4);
+
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set, this->data_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int(dcmtkpp::registry::CommandField) = { dcmtkpp::Message::Command::C_ECHO_RQ };
+ this->check_message_constructor_throw(this->command_set, this->data_set);
+}
diff --git a/tests/code/CMoveRequest.cpp b/tests/code/CMoveRequest.cpp
new file mode 100644
index 0000000..41a490a
--- /dev/null
+++ b/tests/code/CMoveRequest.cpp
@@ -0,0 +1,81 @@
+#define BOOST_TEST_MODULE CMoveRequest
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CMoveRequest.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CMoveRequest>
+{
+ dcmtkpp::DataSet command_set;
+ dcmtkpp::DataSet query;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_MOVE_RQ});
+ this->command_set.add("MessageID", {1234});
+ this->command_set.add("AffectedSOPClassUID",
+ {UID_MOVEPatientRootQueryRetrieveInformationModel});
+ this->command_set.add("Priority", {DIMSE_PRIORITY_MEDIUM});
+ this->command_set.add("MoveDestination", {"destination"});
+
+ this->query.add("PatientName", {"Doe^John"});
+ this->query.add("StudyDescription", {"Brain"});
+ this->query.add("QueryRetrieveLevel", {"STUDY"});
+ }
+
+ virtual void check(dcmtkpp::CMoveRequest const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_MOVE_RQ);
+ BOOST_CHECK_EQUAL(message.get_message_id(), 1234);
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(),
+ UID_MOVEPatientRootQueryRetrieveInformationModel);
+ BOOST_CHECK_EQUAL(message.get_move_destination(), "destination");
+ BOOST_CHECK(message.has_data_set());
+ BOOST_CHECK(message.get_data_set() == this->query);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CMoveRequest const message(
+ 1234, UID_MOVEPatientRootQueryRetrieveInformationModel,
+ DIMSE_PRIORITY_MEDIUM, "destination", this->query);
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RQ};
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingAffectSOPClass, Fixture)
+{
+ this->command_set.remove("AffectedSOPClassUID");
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingPriority, Fixture)
+{
+ this->command_set.remove("Priority");
+ this->check_message_constructor_throw(this->command_set, this->query);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorEmptyQuery, Fixture)
+{
+ dcmtkpp::DataSet empty;
+ this->check_message_constructor_throw(this->command_set, empty);
+}
diff --git a/tests/code/CMoveResponse.cpp b/tests/code/CMoveResponse.cpp
new file mode 100644
index 0000000..ceb7b5b
--- /dev/null
+++ b/tests/code/CMoveResponse.cpp
@@ -0,0 +1,93 @@
+#define BOOST_TEST_MODULE CMoveResponse
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CMoveResponse.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CMoveResponse>
+{
+ dcmtkpp::DataSet command_set;
+ dcmtkpp::DataSet data_set;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_MOVE_RSP});
+ this->command_set.add("MessageIDBeingRespondedTo", {1234});
+ this->command_set.add("Status", {STATUS_Success});
+
+ this->command_set.add("MessageID", {5678});
+ this->command_set.add("AffectedSOPClassUID",
+ {UID_MOVEStudyRootQueryRetrieveInformationModel});
+ this->command_set.add(dcmtkpp::registry::NumberOfRemainingSuboperations, {1});
+ this->command_set.add(dcmtkpp::registry::NumberOfCompletedSuboperations, {2});
+ this->command_set.add(dcmtkpp::registry::NumberOfFailedSuboperations, {3});
+ this->command_set.add(dcmtkpp::registry::NumberOfWarningSuboperations, {4});
+
+ this->data_set.add("PatientName", {"Doe^John"});
+ this->data_set.add("PatientID", {"DJ123"});
+ this->data_set.add("StudyDescription", {"Brain"});
+ this->data_set.add("StudyInstanceUID", {"1.2.3"});
+ }
+
+ virtual void check(dcmtkpp::CMoveResponse const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_MOVE_RSP);
+ BOOST_CHECK_EQUAL(message.get_message_id_being_responded_to(), 1234);
+ BOOST_CHECK_EQUAL(message.get_status(), STATUS_Success);
+
+ BOOST_CHECK(message.has_message_id());
+ BOOST_CHECK_EQUAL(message.get_message_id(), 5678);
+
+ BOOST_CHECK(message.has_affected_sop_class_uid());
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(),
+ UID_MOVEStudyRootQueryRetrieveInformationModel);
+
+ BOOST_CHECK(message.has_number_of_remaining_sub_operations());
+ BOOST_CHECK_EQUAL(message.get_number_of_remaining_sub_operations(), 1);
+
+ BOOST_CHECK(message.has_number_of_completed_sub_operations());
+ BOOST_CHECK_EQUAL(message.get_number_of_completed_sub_operations(), 2);
+
+ BOOST_CHECK(message.has_number_of_failed_sub_operations());
+ BOOST_CHECK_EQUAL(message.get_number_of_failed_sub_operations(), 3);
+
+ BOOST_CHECK(message.has_number_of_warning_sub_operations());
+ BOOST_CHECK_EQUAL(message.get_number_of_warning_sub_operations(), 4);
+
+ BOOST_CHECK(message.has_data_set());
+ BOOST_CHECK(message.get_data_set() == this->data_set);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CMoveResponse message(1234, STATUS_Success, this->data_set);
+ message.set_message_id(5678);
+ message.set_affected_sop_class_uid(
+ UID_MOVEStudyRootQueryRetrieveInformationModel);
+ message.set_number_of_remaining_sub_operations(1);
+ message.set_number_of_completed_sub_operations(2);
+ message.set_number_of_failed_sub_operations(3);
+ message.set_number_of_warning_sub_operations(4);
+
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set, this->data_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RQ};
+ this->check_message_constructor_throw(this->command_set, this->data_set);
+}
diff --git a/tests/code/CStoreRequest.cpp b/tests/code/CStoreRequest.cpp
new file mode 100644
index 0000000..9c9f625
--- /dev/null
+++ b/tests/code/CStoreRequest.cpp
@@ -0,0 +1,88 @@
+#define BOOST_TEST_MODULE CStoreRequest
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CStoreRequest.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CStoreRequest>
+{
+ dcmtkpp::DataSet command_set;
+ dcmtkpp::DataSet data_set;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_STORE_RQ});
+ this->command_set.add("MessageID", {1234});
+ this->command_set.add("AffectedSOPClassUID", {UID_MRImageStorage});
+ this->command_set.add("AffectedSOPInstanceUID", {"1.2.3.4"});
+ this->command_set.add("Priority", {DIMSE_PRIORITY_MEDIUM});
+
+ this->command_set.add("MoveOriginatorApplicationEntityTitle", {"origin"});
+ this->command_set.add("MoveOriginatorMessageID", {5678});
+
+ this->data_set.add("PatientName", {"Doe^John"});
+ this->data_set.add("PatientID", {"DJ123"});
+ this->data_set.add("StudyDescription", {"Brain"});
+ this->data_set.add("StudyInstanceUID", {"1.2.3"});
+ }
+
+ void check(dcmtkpp::CStoreRequest const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_STORE_RQ);
+ BOOST_CHECK_EQUAL(message.get_message_id(), 1234);
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(), UID_MRImageStorage);
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_instance_uid(), "1.2.3.4");
+
+ BOOST_CHECK(message.has_move_originator_ae_title());
+ BOOST_CHECK_EQUAL(message.get_move_originator_ae_title(), "origin");
+
+ BOOST_CHECK(message.has_move_originator_message_id());
+ BOOST_CHECK_EQUAL(message.get_move_originator_message_id(), 5678);
+
+ BOOST_CHECK(message.has_data_set());
+ BOOST_CHECK(message.get_data_set() == this->data_set);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CStoreRequest message(
+ 1234, UID_MRImageStorage, "1.2.3.4", DIMSE_PRIORITY_MEDIUM,
+ this->data_set);
+ message.set_move_originator_ae_title("origin");
+ message.set_move_originator_message_id(5678);
+
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set, this->data_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RSP};
+ this->check_message_constructor_throw(this->command_set, this->data_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingAffectSOPClass, Fixture)
+{
+ this->command_set.remove("AffectedSOPClassUID");
+ this->check_message_constructor_throw(this->command_set, this->data_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorMissingAffectSOPInstance, Fixture)
+{
+ this->command_set.remove("AffectedSOPInstanceUID");
+ this->check_message_constructor_throw(this->command_set, this->data_set);
+}
diff --git a/tests/code/CStoreResponse.cpp b/tests/code/CStoreResponse.cpp
new file mode 100644
index 0000000..77ca267
--- /dev/null
+++ b/tests/code/CStoreResponse.cpp
@@ -0,0 +1,68 @@
+#define BOOST_TEST_MODULE CStoreResponse
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/CStoreResponse.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::CStoreResponse>
+{
+ dcmtkpp::DataSet command_set;
+
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_STORE_RSP});
+ this->command_set.add("MessageIDBeingRespondedTo", {1234});
+ this->command_set.add("Status", {STATUS_Success});
+
+ this->command_set.add("MessageID", {5678});
+ this->command_set.add("AffectedSOPClassUID", {UID_MRImageStorage});
+ this->command_set.add("AffectedSOPInstanceUID", {"1.2.3.4"});
+ }
+
+ void check(dcmtkpp::CStoreResponse const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_STORE_RSP);
+ BOOST_CHECK_EQUAL(message.get_message_id_being_responded_to(), 1234);
+ BOOST_CHECK_EQUAL(message.get_status(), STATUS_Success);
+ BOOST_CHECK(!message.has_data_set());
+
+ BOOST_CHECK(message.has_message_id());
+ BOOST_CHECK_EQUAL(message.get_message_id(), 5678);
+
+ BOOST_CHECK(message.has_affected_sop_class_uid());
+ BOOST_CHECK_EQUAL(
+ message.get_affected_sop_class_uid(), UID_MRImageStorage);
+
+ BOOST_CHECK(message.has_affected_sop_instance_uid());
+ BOOST_CHECK_EQUAL(message.get_affected_sop_instance_uid(), "1.2.3.4");
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::CStoreResponse message(1234, STATUS_Success);
+ message.set_message_id(5678);
+ message.set_affected_sop_class_uid(UID_MRImageStorage);
+ message.set_affected_sop_instance_uid("1.2.3.4");
+
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_ECHO_RQ});
+ this->check_message_constructor_throw(this->command_set);
+}
+
diff --git a/tests/code/Cancellation.cpp b/tests/code/Cancellation.cpp
new file mode 100644
index 0000000..5f2954f
--- /dev/null
+++ b/tests/code/Cancellation.cpp
@@ -0,0 +1,40 @@
+#define BOOST_TEST_MODULE Cancellation
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Cancellation.h"
+
+#include "../MessageFixtureBase.h"
+
+struct Fixture: public MessageFixtureBase<dcmtkpp::Cancellation>
+{
+ dcmtkpp::DataSet command_set;
+ Fixture()
+ {
+ this->command_set.add("CommandField", {dcmtkpp::Message::Command::C_CANCEL_RQ});
+ this->command_set.add("MessageIDBeingRespondedTo", {1234});
+ }
+
+ void check(dcmtkpp::Cancellation const & message)
+ {
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_CANCEL_RQ);
+ BOOST_CHECK_EQUAL(message.get_message_id_being_responded_to(), 1234);
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(Constructor, Fixture)
+{
+ dcmtkpp::Cancellation const message(1234);
+ this->check(message);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructor, Fixture)
+{
+ this->check_message_constructor(this->command_set);
+}
+
+BOOST_FIXTURE_TEST_CASE(MessageConstructorWrongCommandField, Fixture)
+{
+ this->command_set.as_int("CommandField") = {dcmtkpp::Message::Command::C_ECHO_RQ};
+ this->check_message_constructor_throw(this->command_set);
+}
diff --git a/tests/code/DataSet.cpp b/tests/code/DataSet.cpp
new file mode 100644
index 0000000..f28aa3c
--- /dev/null
+++ b/tests/code/DataSet.cpp
@@ -0,0 +1,273 @@
+#define BOOST_TEST_MODULE DataSet
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Tag.h"
+#include "dcmtkpp/VR.h"
+
+BOOST_AUTO_TEST_CASE(Empty)
+{
+ dcmtkpp::DataSet dataset;
+ BOOST_CHECK(dataset.empty());
+ BOOST_CHECK_EQUAL(dataset.size(), 0);
+ BOOST_CHECK(!dataset.has(dcmtkpp::Tag("PatientName")));
+}
+
+BOOST_AUTO_TEST_CASE(AddExplicitVR)
+{
+ dcmtkpp::Tag const tag("PatientName");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag, dcmtkpp::VR::PN);
+
+ BOOST_CHECK(!dataset.empty());
+ BOOST_CHECK_EQUAL(dataset.size(), 1);
+ BOOST_CHECK(dataset.has(tag));
+ BOOST_CHECK(dataset.get_vr(tag) == dcmtkpp::VR::PN);
+}
+
+BOOST_AUTO_TEST_CASE(AddImplicitVR)
+{
+ dcmtkpp::Tag const tag("PatientName");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+
+ BOOST_CHECK(!dataset.empty());
+ BOOST_CHECK_EQUAL(dataset.size(), 1);
+ BOOST_CHECK(dataset.has(tag));
+ BOOST_CHECK(dataset.get_vr(tag) == dcmtkpp::VR::PN);
+}
+
+BOOST_AUTO_TEST_CASE(AddValueExplicitVR)
+{
+ dcmtkpp::Tag const tag("PatientName");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag, { "Doe^John"}, dcmtkpp::VR::PN);
+
+ BOOST_CHECK(!dataset.empty());
+ BOOST_CHECK_EQUAL(dataset.size(), 1);
+ BOOST_CHECK(dataset.has(tag));
+ BOOST_CHECK(dataset.get_vr(tag) == dcmtkpp::VR::PN);
+ BOOST_CHECK(dataset.as_string(tag) == dcmtkpp::Value::Strings({ "Doe^John" }));
+}
+
+BOOST_AUTO_TEST_CASE(AddValueImplicitVR)
+{
+ dcmtkpp::Tag const tag("PatientName");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag, { "Doe^John"});
+
+ BOOST_CHECK(!dataset.empty());
+ BOOST_CHECK_EQUAL(dataset.size(), 1);
+ BOOST_CHECK(dataset.has(tag));
+ BOOST_CHECK(dataset.get_vr(tag) == dcmtkpp::VR::PN);
+ BOOST_CHECK(dataset.as_string(tag) == dcmtkpp::Value::Strings({ "Doe^John" }));
+}
+
+BOOST_AUTO_TEST_CASE(AddInvalidTag)
+{
+ dcmtkpp::Tag const tag(0xdead, 0xbeef);
+ dcmtkpp::DataSet dataset;
+
+ BOOST_CHECK_THROW(dataset.add(tag), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(AddInt)
+{
+ dcmtkpp::Tag const tag("Rows");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+
+ BOOST_CHECK(dataset.is_int(tag));
+ BOOST_CHECK(dataset.empty(tag));
+ BOOST_CHECK_EQUAL(dataset.size(tag), 0);
+
+ std::vector<int64_t> const & value = dataset.as_int(tag);
+ BOOST_CHECK(value.empty());
+}
+
+BOOST_AUTO_TEST_CASE(AddDouble)
+{
+ dcmtkpp::Tag const tag("SpacingBetweenSlices");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+
+ BOOST_CHECK(dataset.is_real(tag));
+ BOOST_CHECK(dataset.empty(tag));
+ BOOST_CHECK_EQUAL(dataset.size(tag), 0);
+
+ std::vector<double> const & value = dataset.as_real(tag);
+ BOOST_CHECK(value.empty());
+}
+
+BOOST_AUTO_TEST_CASE(AddString)
+{
+ dcmtkpp::Tag const tag("PatientID");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+
+ BOOST_CHECK(dataset.is_string(tag));
+ BOOST_CHECK(dataset.empty(tag));
+ BOOST_CHECK_EQUAL(dataset.size(tag), 0);
+
+ std::vector<std::string> const & value = dataset.as_string(tag);
+ BOOST_CHECK(value.empty());
+}
+
+BOOST_AUTO_TEST_CASE(AddDataSet)
+{
+ dcmtkpp::Tag const tag("ReferencedStudySequence");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+
+ BOOST_CHECK(dataset.is_data_set(tag));
+ BOOST_CHECK(dataset.empty(tag));
+ BOOST_CHECK_EQUAL(dataset.size(tag), 0);
+
+ dcmtkpp::Value::DataSets const & value = dataset.as_data_set(tag);
+ BOOST_CHECK(value.empty());
+}
+
+BOOST_AUTO_TEST_CASE(ModifyInt)
+{
+ dcmtkpp::Tag const tag("Rows");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+ dataset.as_int(tag).push_back(256);
+
+ BOOST_CHECK(!dataset.empty(tag));
+ BOOST_CHECK_EQUAL(dataset.size(tag), 1);
+ BOOST_CHECK_EQUAL(dataset.as_int(tag, 0), 256);
+}
+
+BOOST_AUTO_TEST_CASE(ModifyDouble)
+{
+ dcmtkpp::Tag const tag("SpacingBetweenSlices");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+ dataset.as_real(tag).push_back(3.14);
+
+ BOOST_CHECK(!dataset.empty(tag));
+ BOOST_CHECK_EQUAL(dataset.size(tag), 1);
+ BOOST_CHECK_EQUAL(dataset.as_real(tag, 0), 3.14);
+}
+
+BOOST_AUTO_TEST_CASE(ModifyString)
+{
+ dcmtkpp::Tag const tag("PatientID");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+ dataset.as_string(tag).push_back("FooBar");
+
+ BOOST_CHECK(!dataset.empty(tag));
+ BOOST_CHECK_EQUAL(dataset.size(tag), 1);
+ BOOST_CHECK_EQUAL(dataset.as_string(tag, 0), "FooBar");
+}
+
+BOOST_AUTO_TEST_CASE(ModifyDataSet)
+{
+ dcmtkpp::Tag const tag("ReferencedStudySequence");
+
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+
+ dcmtkpp::DataSet item;
+ item.add("PatientID", {"DJ1234"});
+ dataset.as_data_set(tag).push_back(item);
+
+ BOOST_CHECK(!dataset.empty(tag));
+ BOOST_CHECK_EQUAL(dataset.size(tag), 1);
+
+ dcmtkpp::Value::DataSets const & value = dataset.as_data_set(tag);
+ BOOST_CHECK_EQUAL(value.size(), 1);
+ BOOST_CHECK_EQUAL(value.size(), 1);
+ BOOST_CHECK_EQUAL(value[0].size(), 1);
+ BOOST_CHECK(value[0].has("PatientID"));
+ BOOST_CHECK(
+ value[0].as_string("PatientID") == dcmtkpp::Value::Strings({"DJ1234"}));
+}
+
+BOOST_AUTO_TEST_CASE(GetVRMissing)
+{
+ dcmtkpp::Tag const tag("PatientID");
+ dcmtkpp::DataSet dataset;
+ BOOST_CHECK_THROW(dataset.get_vr(tag), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(TestEmptyMissing)
+{
+ dcmtkpp::Tag const tag("PatientID");
+ dcmtkpp::DataSet dataset;
+ BOOST_CHECK_THROW(dataset.empty(tag), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(SizeMissing)
+{
+ dcmtkpp::Tag const tag("PatientID");
+ dcmtkpp::DataSet dataset;
+ BOOST_CHECK_THROW(dataset.size(tag), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Remove)
+{
+ dcmtkpp::Tag const tag("PatientID");
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+
+ dataset.remove(tag);
+ BOOST_CHECK(!dataset.has(tag));
+}
+
+BOOST_AUTO_TEST_CASE(RemoveMissing)
+{
+ dcmtkpp::Tag const tag("PatientID");
+ dcmtkpp::DataSet dataset;
+ dataset.add(tag);
+
+ dcmtkpp::Tag const other("PatientName");
+
+ BOOST_CHECK_THROW(
+ dataset.remove(other),
+ dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Equality)
+{
+ dcmtkpp::DataSet dataset1;
+ dataset1.add("PatientID", {"DJ1234"});
+
+ dcmtkpp::DataSet dataset2;
+ dataset2.add("PatientID", {"DJ1234"});
+
+ dcmtkpp::DataSet dataset3;
+ dataset3.add("PatientAge", {"042Y"});
+
+ BOOST_CHECK(dataset1 == dataset2);
+ BOOST_CHECK(! (dataset1 == dataset3));
+}
+
+BOOST_AUTO_TEST_CASE(Difference)
+{
+ dcmtkpp::DataSet dataset1;
+ dataset1.add("PatientID", {"DJ1234"});
+
+ dcmtkpp::DataSet dataset2;
+ dataset2.add("PatientID", {"DJ1234"});
+
+ dcmtkpp::DataSet dataset3;
+ dataset3.add("PatientAge", {"042Y"});
+
+ BOOST_CHECK(! (dataset1 != dataset2));
+ BOOST_CHECK(dataset1 != dataset3);
+}
diff --git a/tests/code/Element.cpp b/tests/code/Element.cpp
new file mode 100644
index 0000000..23c82e7
--- /dev/null
+++ b/tests/code/Element.cpp
@@ -0,0 +1,160 @@
+#define BOOST_TEST_MODULE Element
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Element.h"
+#include "dcmtkpp/Exception.h"
+
+BOOST_AUTO_TEST_CASE(Empty)
+{
+ dcmtkpp::Element element;
+ BOOST_CHECK(element.empty());
+ BOOST_CHECK_EQUAL(element.size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(Int)
+{
+ dcmtkpp::Element const element((dcmtkpp::Value::Integers()));
+ BOOST_CHECK(element.is_int());
+
+ std::vector<int64_t> const & value = element.as_int();
+ BOOST_CHECK(value.empty());
+}
+
+BOOST_AUTO_TEST_CASE(ModifyInt)
+{
+ dcmtkpp::Element element({0});
+ element.as_int().push_back(1);
+
+ BOOST_CHECK(!element.empty());
+ BOOST_CHECK_EQUAL(element.size(), 2);
+
+ std::vector<int64_t> const & value = element.as_int();
+ BOOST_CHECK(value == dcmtkpp::Value::Integers({0, 1}));
+}
+
+BOOST_AUTO_TEST_CASE(IntWrong)
+{
+ dcmtkpp::Element element((dcmtkpp::Value::Integers()));
+ BOOST_CHECK_THROW(element.as_real(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(element.as_string(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Double)
+{
+ dcmtkpp::Element const element((dcmtkpp::Value::Reals()));
+ BOOST_CHECK(element.is_real());
+
+ std::vector<double> const & value = element.as_real();
+ BOOST_CHECK(value.empty());
+}
+
+BOOST_AUTO_TEST_CASE(ModifyDouble)
+{
+ dcmtkpp::Element element({0.});
+ element.as_real().push_back(1.5);
+
+ BOOST_CHECK(!element.empty());
+ BOOST_CHECK_EQUAL(element.size(), 2);
+
+ std::vector<double> const & value = element.as_real();
+ BOOST_CHECK(value == dcmtkpp::Value::Reals({0., 1.5}));
+}
+
+BOOST_AUTO_TEST_CASE(DoubleWrong)
+{
+ dcmtkpp::Element element((dcmtkpp::Value::Reals()));
+ BOOST_CHECK_THROW(element.as_int(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(element.as_string(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(element.as_data_set(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(String)
+{
+ dcmtkpp::Element const element((dcmtkpp::Value::Strings()));
+ BOOST_CHECK(element.is_string());
+
+ std::vector<std::string> const & value = element.as_string();
+ BOOST_CHECK(value.empty());
+}
+
+BOOST_AUTO_TEST_CASE(ModifyString)
+{
+ dcmtkpp::Element element({""});
+ element.as_string().push_back("foo");
+
+ BOOST_CHECK(!element.empty());
+ BOOST_CHECK_EQUAL(element.size(), 2);
+
+ std::vector<std::string> const & value = element.as_string();
+ BOOST_CHECK(value == dcmtkpp::Value::Strings({"", "foo"}));
+}
+
+BOOST_AUTO_TEST_CASE(StringWrong)
+{
+ dcmtkpp::Element element((dcmtkpp::Value::Strings()));
+ BOOST_CHECK_THROW(element.as_int(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(element.as_real(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(element.as_data_set(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(DataSet)
+{
+ dcmtkpp::Element const element((dcmtkpp::Value::DataSets()));
+ BOOST_CHECK(element.is_data_set());
+
+ dcmtkpp::Value::DataSets const & value = element.as_data_set();
+ BOOST_CHECK(value.empty());
+}
+
+BOOST_AUTO_TEST_CASE(ModifyDataSet)
+{
+ dcmtkpp::Element element((dcmtkpp::Value::DataSets()));
+
+ dcmtkpp::DataSet data_set;
+ data_set.add("PatientID");
+ data_set.as_string("PatientID").push_back("DJ1234");
+ element.as_data_set().push_back(data_set);
+
+ BOOST_CHECK(!element.empty());
+ BOOST_CHECK_EQUAL(element.size(), 1);
+
+ dcmtkpp::Value::DataSets const & value = element.as_data_set();
+ BOOST_CHECK_EQUAL(value.size(), 1);
+ BOOST_CHECK_EQUAL(value[0].size(), 1);
+ BOOST_CHECK(value[0].has("PatientID"));
+ BOOST_CHECK(
+ value[0].as_string("PatientID") == dcmtkpp::Value::Strings({"DJ1234"}));
+}
+
+BOOST_AUTO_TEST_CASE(DataSetWrong)
+{
+ dcmtkpp::Element element((dcmtkpp::Value::DataSets()));
+ BOOST_CHECK_THROW(element.as_int(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(element.as_real(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(element.as_string(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Equality)
+{
+ dcmtkpp::Element const element1({12,34}, dcmtkpp::VR::US);
+ dcmtkpp::Element const element2({12,34}, dcmtkpp::VR::US);
+ dcmtkpp::Element const element3({12.,34.}, dcmtkpp::VR::FL);
+ dcmtkpp::Element const element4({12,34}, dcmtkpp::VR::UL);
+
+ BOOST_CHECK(element1 == element2);
+ BOOST_CHECK(! (element1 == element3));
+ BOOST_CHECK(! (element1 == element4));
+}
+
+BOOST_AUTO_TEST_CASE(Difference)
+{
+ dcmtkpp::Element const element1({12,34}, dcmtkpp::VR::US);
+ dcmtkpp::Element const element2({12,34}, dcmtkpp::VR::US);
+ dcmtkpp::Element const element3({12.,34.}, dcmtkpp::VR::FL);
+ dcmtkpp::Element const element4({12,34}, dcmtkpp::VR::UL);
+
+ BOOST_CHECK(! (element1 != element2));
+ BOOST_CHECK(element1 != element3);
+ BOOST_CHECK(element1 != element4);
+}
diff --git a/tests/code/ElementAccessor.cpp b/tests/code/ElementAccessor.cpp
new file mode 100644
index 0000000..4e8ac3e
--- /dev/null
+++ b/tests/code/ElementAccessor.cpp
@@ -0,0 +1,125 @@
+#define BOOST_TEST_MODULE ElementAccessor
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dcdatset.h>
+#include <dcmtk/dcmdata/dcdeftag.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/ElementAccessor.h"
+#include "dcmtkpp/VRTraits.h"
+
+struct Fixture
+{
+ DcmDataset dataset;
+
+ Fixture()
+ {
+ OFCondition condition;
+ condition = dataset.putAndInsertOFStringArray(DCM_PatientID, "DJ123");
+ if(condition.bad())
+ {
+ throw dcmtkpp::Exception(condition);
+ }
+
+ condition = dataset.putAndInsertUint16(DCM_MessageID, 1234);
+ if(condition.bad())
+ {
+ throw dcmtkpp::Exception(condition);
+ }
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(GetCorrectTypeString, Fixture)
+{
+ BOOST_CHECK_EQUAL(
+ dcmtkpp::ElementAccessor<std::string>::get(this->dataset, DCM_PatientID),
+ "DJ123");
+}
+
+BOOST_FIXTURE_TEST_CASE(GetCorrectVRString, Fixture)
+{
+ BOOST_CHECK_EQUAL(
+ dcmtkpp::ElementAccessor<
+ typename dcmtkpp::VRTraits<EVR_LO>::ValueType
+ >::get(this->dataset, DCM_PatientID),
+ "DJ123");
+}
+
+BOOST_FIXTURE_TEST_CASE(GetCorrectTypeNonString, Fixture)
+{
+ BOOST_CHECK_EQUAL(
+ dcmtkpp::ElementAccessor<Uint16>::get(this->dataset, DCM_MessageID),
+ 1234);
+}
+
+BOOST_FIXTURE_TEST_CASE(GetCorrectVRNonString, Fixture)
+{
+ BOOST_CHECK_EQUAL(
+ dcmtkpp::ElementAccessor<
+ typename dcmtkpp::VRTraits<EVR_US>::ValueType
+ >::get(this->dataset, DCM_MessageID),
+ 1234);
+}
+
+BOOST_FIXTURE_TEST_CASE(GetWrongTypeString, Fixture)
+{
+ BOOST_CHECK_THROW(
+ dcmtkpp::ElementAccessor<Float32>::get(this->dataset, DCM_PatientID),
+ dcmtkpp::Exception);
+}
+
+BOOST_FIXTURE_TEST_CASE(GetWrongTypeNonString, Fixture)
+{
+ BOOST_CHECK_THROW(
+ dcmtkpp::ElementAccessor<Float32>::get(this->dataset, DCM_MessageID),
+ dcmtkpp::Exception);
+}
+
+BOOST_FIXTURE_TEST_CASE(SetEmpty, Fixture)
+{
+ dcmtkpp::ElementAccessor<std::string>::set(this->dataset, DCM_PatientName, "FOO");
+ OFString value;
+ OFCondition const condition =
+ this->dataset.findAndGetOFString(DCM_PatientName, value);
+ BOOST_REQUIRE(condition.good());
+ BOOST_CHECK_EQUAL(std::string(value.c_str()), "FOO");
+}
+
+BOOST_FIXTURE_TEST_CASE(SetWrongTypeString, Fixture)
+{
+ BOOST_CHECK_THROW(
+ dcmtkpp::ElementAccessor<Float32>::set(
+ this->dataset, DCM_PatientName, 1.234),
+ dcmtkpp::Exception);
+}
+
+BOOST_FIXTURE_TEST_CASE(SetWrongTypeNonString, Fixture)
+{
+ BOOST_CHECK_THROW(
+ dcmtkpp::ElementAccessor<Float64>::set(
+ this->dataset, DCM_Status, STATUS_Success),
+ dcmtkpp::Exception);
+}
+
+BOOST_FIXTURE_TEST_CASE(SetExisting, Fixture)
+{
+ dcmtkpp::ElementAccessor<std::string>::set(this->dataset, DCM_PatientID, "FOO");
+ OFString value;
+ OFCondition const condition =
+ this->dataset.findAndGetOFString(DCM_PatientID, value);
+ BOOST_REQUIRE(condition.good());
+ BOOST_CHECK_EQUAL(std::string(value.c_str()), "FOO");
+}
+
+BOOST_FIXTURE_TEST_CASE(Has, Fixture)
+{
+ BOOST_CHECK(
+ dcmtkpp::ElementAccessor<std::string>::has(this->dataset, DCM_PatientID));
+}
+
+BOOST_FIXTURE_TEST_CASE(HasNot, Fixture)
+{
+ BOOST_CHECK(
+ !dcmtkpp::ElementAccessor<std::string>::has(this->dataset, DCM_PatientName));
+}
diff --git a/tests/code/Exception.cpp b/tests/code/Exception.cpp
new file mode 100644
index 0000000..c0939d5
--- /dev/null
+++ b/tests/code/Exception.cpp
@@ -0,0 +1,36 @@
+#define BOOST_TEST_MODULE Message
+#include <boost/test/unit_test.hpp>
+
+#include <ostream>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/ofstd/ofcond.h>
+
+#include "dcmtkpp/Exception.h"
+
+namespace dcmtkpp
+{
+
+std::ostream & operator<<(std::ostream & stream, Exception::Source const & type)
+{
+ stream << int(type);
+ return stream;
+}
+
+}
+
+BOOST_AUTO_TEST_CASE(StringConstructor)
+{
+ dcmtkpp::Exception const exception("foo");
+ BOOST_CHECK_EQUAL(exception.get_source(), dcmtkpp::Exception::Source::Message);
+ BOOST_CHECK_EQUAL(exception.what(), "foo");
+ BOOST_CHECK_THROW(exception.get_condition(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(ConditionConstructor)
+{
+ dcmtkpp::Exception const exception(EC_IllegalParameter);
+ BOOST_CHECK_EQUAL(exception.get_source(), dcmtkpp::Exception::Source::Condition);
+ BOOST_CHECK_EQUAL(exception.what(), EC_IllegalParameter.text());
+ BOOST_CHECK(exception.get_condition() == EC_IllegalParameter);
+}
diff --git a/tests/code/FindSCU.cpp b/tests/code/FindSCU.cpp
new file mode 100644
index 0000000..a7758df
--- /dev/null
+++ b/tests/code/FindSCU.cpp
@@ -0,0 +1,65 @@
+#define BOOST_TEST_MODULE FindSCU
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/FindSCU.h"
+
+#include "../PeerFixtureBase.h"
+
+struct Fixture: public PeerFixtureBase
+{
+ static bool called;
+
+ dcmtkpp::DataSet query;
+
+ Fixture()
+ : PeerFixtureBase(NET_REQUESTOR, 104, 10,
+ {
+ {
+ UID_FINDPatientRootQueryRetrieveInformationModel,
+ { UID_LittleEndianImplicitTransferSyntax }
+ }
+ })
+ {
+ Fixture::called = false;
+
+ this->query.add("QueryRetrieveLevel", {"PATIENT"});
+ this->query.add("PatientName", {"Doe^John"});
+ this->query.add("PatientID");
+ }
+
+
+ static void callback(dcmtkpp::DataSet const &)
+ {
+ Fixture::called = true;
+ }
+};
+
+bool Fixture::called = false;
+
+BOOST_FIXTURE_TEST_CASE(Find, Fixture)
+{
+ dcmtkpp::FindSCU scu;
+ scu.set_network(&this->network);
+ scu.set_association(&this->association);
+
+ scu.set_affected_sop_class(UID_FINDPatientRootQueryRetrieveInformationModel);
+ auto const results = scu.find(this->query);
+
+ BOOST_REQUIRE_EQUAL(results.size(), 1);
+ BOOST_CHECK(
+ results[0].as_string("PatientID") ==
+ dcmtkpp::Value::Strings({"DJ001"}));
+}
+
+BOOST_FIXTURE_TEST_CASE(FindCallback, Fixture)
+{
+ dcmtkpp::FindSCU scu;
+ scu.set_network(&this->network);
+ scu.set_association(&this->association);
+
+ scu.set_affected_sop_class(UID_FINDPatientRootQueryRetrieveInformationModel);
+ scu.find(this->query, Fixture::callback);
+
+ BOOST_CHECK(Fixture::called);
+}
diff --git a/tests/code/GetSCU.cpp b/tests/code/GetSCU.cpp
new file mode 100644
index 0000000..d588760
--- /dev/null
+++ b/tests/code/GetSCU.cpp
@@ -0,0 +1,69 @@
+#define BOOST_TEST_MODULE GetSCU
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/GetSCU.h"
+
+#include "../PeerFixtureBase.h"
+
+struct Fixture: public PeerFixtureBase
+{
+ static bool called;
+
+ dcmtkpp::DataSet query;
+
+ Fixture()
+ : PeerFixtureBase(NET_REQUESTOR, 104, 10,
+ {
+ {
+ UID_GETPatientRootQueryRetrieveInformationModel,
+ { UID_LittleEndianImplicitTransferSyntax }
+ },
+ {
+ UID_RawDataStorage, { UID_LittleEndianImplicitTransferSyntax },
+ ASC_SC_ROLE_SCP
+ }
+ })
+ {
+ Fixture::called = false;
+
+ this->query.add("QueryRetrieveLevel", {"PATIENT"});
+ this->query.add("PatientName", {"Doe^John"});
+ }
+
+
+ static void callback(dcmtkpp::DataSet const &)
+ {
+ Fixture::called = true;
+ }
+};
+
+bool Fixture::called = false;
+
+BOOST_FIXTURE_TEST_CASE(Get, Fixture)
+{
+ dcmtkpp::GetSCU scu;
+ scu.set_network(&this->network);
+ scu.set_association(&this->association);
+
+ scu.set_affected_sop_class(UID_GETPatientRootQueryRetrieveInformationModel);
+ auto const results = scu.get(this->query);
+
+ BOOST_REQUIRE_EQUAL(results.size(), 1);
+ BOOST_CHECK(
+ results[0].as_string("SOPInstanceUID") ==
+ dcmtkpp::Value::Strings({"2.25.95090344942250266709587559073467305647"}));
+}
+
+BOOST_FIXTURE_TEST_CASE(GetCallback, Fixture)
+{
+ dcmtkpp::GetSCU scu;
+ scu.set_network(&this->network);
+ scu.set_association(&this->association);
+
+ scu.set_affected_sop_class(UID_GETPatientRootQueryRetrieveInformationModel);
+ scu.get(this->query, Fixture::callback);
+
+ BOOST_CHECK(Fixture::called);
+}
+
diff --git a/tests/code/Message.cpp b/tests/code/Message.cpp
new file mode 100644
index 0000000..0b8e836
--- /dev/null
+++ b/tests/code/Message.cpp
@@ -0,0 +1,57 @@
+#define BOOST_TEST_MODULE Message
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+
+BOOST_AUTO_TEST_CASE(DefaultConstructor)
+{
+ dcmtkpp::Message const message;
+
+ // Command Set might not be empty (Command Group Length, Data Set Type)
+ BOOST_CHECK(!message.has_data_set());
+}
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+ dcmtkpp::DataSet command_set;
+ command_set.add("CommandField", {dcmtkpp::Message::Command::C_ECHO_RQ});
+
+ dcmtkpp::DataSet data_set;
+
+ dcmtkpp::Message const message(command_set, data_set);
+
+ BOOST_CHECK_EQUAL(
+ message.get_command_set().as_int("CommandField", 0),
+ dcmtkpp::Message::Command::C_ECHO_RQ);
+
+ BOOST_CHECK(message.has_data_set());
+ BOOST_CHECK(message.get_data_set().empty());
+
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_ECHO_RQ);
+}
+
+BOOST_AUTO_TEST_CASE(CommandField)
+{
+ dcmtkpp::Message message;
+ message.set_command_field(dcmtkpp::Message::Command::C_FIND_RSP);
+
+ BOOST_CHECK(
+ message.get_command_set().as_int("CommandField") ==
+ dcmtkpp::Value::Integers({dcmtkpp::Message::Command::C_FIND_RSP}));
+ BOOST_CHECK_EQUAL(message.get_command_field(), dcmtkpp::Message::Command::C_FIND_RSP);
+}
+
+BOOST_AUTO_TEST_CASE(DeleteDataSet)
+{
+ dcmtkpp::DataSet command_set;
+ dcmtkpp::DataSet data_set;
+
+ dcmtkpp::Message message(command_set, data_set);
+
+ BOOST_CHECK(message.has_data_set());
+
+ message.delete_data_set();
+
+ BOOST_CHECK(!message.has_data_set());
+}
diff --git a/tests/code/MoveSCU.cpp b/tests/code/MoveSCU.cpp
new file mode 100644
index 0000000..11bf2c9
--- /dev/null
+++ b/tests/code/MoveSCU.cpp
@@ -0,0 +1,82 @@
+#define BOOST_TEST_MODULE MoveSCU
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/MoveSCU.h"
+
+#include "../PeerFixtureBase.h"
+
+struct Fixture: public PeerFixtureBase
+{
+ static bool called;
+
+ dcmtkpp::DataSet query;
+
+ Fixture()
+ : PeerFixtureBase(NET_ACCEPTORREQUESTOR, 11113, 10,
+ {
+ {
+ UID_MOVEPatientRootQueryRetrieveInformationModel,
+ { UID_LittleEndianImplicitTransferSyntax }
+ },
+ {
+ UID_RawDataStorage, { UID_LittleEndianImplicitTransferSyntax },
+ ASC_SC_ROLE_SCP
+ }
+ })
+ {
+ Fixture::called = false;
+
+ this->query.add("QueryRetrieveLevel", {"PATIENT"});
+ this->query.add("PatientName", {"Doe^John"});
+ }
+
+ static void callback(dcmtkpp::DataSet const &)
+ {
+ Fixture::called = true;
+ }
+};
+
+bool Fixture::called = false;
+
+BOOST_AUTO_TEST_CASE(DefaultConstructor)
+{
+ dcmtkpp::MoveSCU const scu;
+ BOOST_CHECK_EQUAL(scu.get_move_destination(), "");
+}
+
+BOOST_AUTO_TEST_CASE(MoveDestination)
+{
+ dcmtkpp::MoveSCU scu;
+ scu.set_move_destination("remote");
+ BOOST_CHECK_EQUAL(scu.get_move_destination(), "remote");
+}
+
+BOOST_FIXTURE_TEST_CASE(Move, Fixture)
+{
+ dcmtkpp::MoveSCU scu;
+ scu.set_network(&this->network);
+ scu.set_association(&this->association);
+ scu.set_move_destination("LOCAL");
+
+ scu.set_affected_sop_class(UID_MOVEPatientRootQueryRetrieveInformationModel);
+ auto const results = scu.move(this->query);
+
+ BOOST_REQUIRE_EQUAL(results.size(), 1);
+ BOOST_CHECK(
+ results[0].as_string("SOPInstanceUID") ==
+ dcmtkpp::Value::Strings{"2.25.95090344942250266709587559073467305647"});
+}
+
+BOOST_FIXTURE_TEST_CASE(MoveCallback, Fixture)
+{
+ dcmtkpp::MoveSCU scu;
+ scu.set_network(&this->network);
+ scu.set_association(&this->association);
+ scu.set_move_destination("LOCAL");
+
+ scu.set_affected_sop_class(UID_MOVEPatientRootQueryRetrieveInformationModel);
+ scu.move(this->query, Fixture::callback);
+
+ BOOST_CHECK(Fixture::called);
+}
diff --git a/tests/code/Network.cpp b/tests/code/Network.cpp
new file mode 100644
index 0000000..f2594f9
--- /dev/null
+++ b/tests/code/Network.cpp
@@ -0,0 +1,156 @@
+#define BOOST_TEST_MODULE Network
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/assoc.h>
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Network.h"
+
+BOOST_AUTO_TEST_CASE(DefaultConstructor)
+{
+ dcmtkpp::Network network;
+
+ BOOST_CHECK_EQUAL(network.get_role(), NET_REQUESTOR);
+ BOOST_CHECK_EQUAL(network.get_port(), 0);
+ BOOST_CHECK_EQUAL(network.get_timeout(), 30);
+ BOOST_CHECK_EQUAL(network.get_options(), 0);
+
+ BOOST_CHECK(!network.is_initialized());
+ BOOST_CHECK_EQUAL(network.get_network(), static_cast<T_ASC_Network*>(NULL));
+}
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+ dcmtkpp::Network network(NET_ACCEPTOR, 11112, 10, 1);
+
+ BOOST_CHECK_EQUAL(network.get_role(), NET_ACCEPTOR);
+ BOOST_CHECK_EQUAL(network.get_port(), 11112);
+ BOOST_CHECK_EQUAL(network.get_timeout(), 10);
+ BOOST_CHECK_EQUAL(network.get_options(), 1);
+
+ BOOST_CHECK(!network.is_initialized());
+ BOOST_CHECK_EQUAL(network.get_network(), static_cast<T_ASC_Network*>(NULL));
+}
+
+BOOST_AUTO_TEST_CASE(CopyConstructor)
+{
+ dcmtkpp::Network network(NET_ACCEPTOR, 11112, 10, 1);
+ dcmtkpp::Network other(network);
+
+ BOOST_CHECK_EQUAL(other.get_role(), network.get_role());
+ BOOST_CHECK_EQUAL(other.get_port(), network.get_port());
+ BOOST_CHECK_EQUAL(other.get_timeout(), network.get_timeout());
+ BOOST_CHECK_EQUAL(other.get_options(), network.get_options());
+ BOOST_CHECK_EQUAL(other.is_initialized(), network.is_initialized());
+ BOOST_CHECK_EQUAL(other.get_network(), network.get_network());
+}
+
+BOOST_AUTO_TEST_CASE(Assignment)
+{
+ dcmtkpp::Network network(NET_ACCEPTOR, 11112, 10, 1);
+ dcmtkpp::Network other(NET_REQUESTOR, 112, 30, 0);
+ other = network;
+
+ BOOST_CHECK_EQUAL(other.get_role(), network.get_role());
+ BOOST_CHECK_EQUAL(other.get_port(), network.get_port());
+ BOOST_CHECK_EQUAL(other.get_timeout(), network.get_timeout());
+ BOOST_CHECK_EQUAL(other.get_options(), network.get_options());
+ BOOST_CHECK_EQUAL(other.is_initialized(), network.is_initialized());
+ BOOST_CHECK_EQUAL(other.get_network(), network.get_network());
+}
+
+BOOST_AUTO_TEST_CASE(Role)
+{
+ dcmtkpp::Network network;
+ network.set_role(NET_ACCEPTOR);
+
+ BOOST_CHECK_EQUAL(network.get_role(), NET_ACCEPTOR);
+}
+
+BOOST_AUTO_TEST_CASE(RoleAssociated)
+{
+ dcmtkpp::Network network;
+ network.initialize();
+
+ BOOST_CHECK_THROW(network.set_role(NET_ACCEPTOR), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Port)
+{
+ dcmtkpp::Network network;
+ network.set_port(1234);
+
+ BOOST_CHECK_EQUAL(network.get_port(), 1234);
+}
+
+BOOST_AUTO_TEST_CASE(PortAssociated)
+{
+ dcmtkpp::Network network;
+ network.initialize();
+
+ BOOST_CHECK_THROW(network.set_port(1234), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Timeout)
+{
+ dcmtkpp::Network network;
+ network.set_timeout(10);
+
+ BOOST_CHECK_EQUAL(network.get_timeout(), 10);
+}
+
+BOOST_AUTO_TEST_CASE(TimeoutAssociated)
+{
+ dcmtkpp::Network network;
+ network.initialize();
+
+ BOOST_CHECK_THROW(network.set_timeout(10), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Options)
+{
+ dcmtkpp::Network network;
+ network.set_options(1);
+
+ BOOST_CHECK_EQUAL(network.get_options(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(OptionsAssociated)
+{
+ dcmtkpp::Network network;
+ network.initialize();
+
+ BOOST_CHECK_THROW(network.set_options(1), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Initialize)
+{
+ dcmtkpp::Network network(NET_REQUESTOR, 11112, 1, 0);
+ network.initialize();
+
+ BOOST_CHECK(network.is_initialized());
+ BOOST_CHECK_NE(network.get_network(), static_cast<T_ASC_Network*>(NULL));
+}
+
+BOOST_AUTO_TEST_CASE(Drop)
+{
+ dcmtkpp::Network network(NET_REQUESTOR, 11112, 1, 0);
+ network.initialize();
+ network.drop();
+ BOOST_CHECK(!network.is_initialized());
+ BOOST_CHECK_EQUAL(network.get_network(), static_cast<T_ASC_Network*>(NULL));
+}
+
+BOOST_AUTO_TEST_CASE(InitializeTwice)
+{
+ dcmtkpp::Network network(NET_REQUESTOR, 11112, 1, 0);
+ network.initialize();
+ BOOST_REQUIRE_THROW(network.initialize(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(DropNotInitialized)
+{
+ dcmtkpp::Network network;
+ BOOST_REQUIRE_THROW(network.drop(), dcmtkpp::Exception);
+}
diff --git a/tests/code/Request.cpp b/tests/code/Request.cpp
new file mode 100644
index 0000000..c040689
--- /dev/null
+++ b/tests/code/Request.cpp
@@ -0,0 +1,27 @@
+#define BOOST_TEST_MODULE Request
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/Request.h"
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+ dcmtkpp::Request const message(1234);
+
+ BOOST_CHECK_EQUAL(message.get_message_id(), 1234);
+}
+
+BOOST_AUTO_TEST_CASE(MessageConstructor)
+{
+ dcmtkpp::DataSet command_set;
+ command_set.add("MessageID", {1234});
+ dcmtkpp::Message const generic_message(command_set);
+
+ dcmtkpp::Request const message(generic_message);
+
+ BOOST_CHECK_EQUAL(message.get_message_id(), 1234);
+ BOOST_CHECK(!message.has_data_set());
+}
diff --git a/tests/code/Response.cpp b/tests/code/Response.cpp
new file mode 100644
index 0000000..85070a2
--- /dev/null
+++ b/tests/code/Response.cpp
@@ -0,0 +1,31 @@
+#define BOOST_TEST_MODULE Response
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmnet/dimse.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Message.h"
+#include "dcmtkpp/Response.h"
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+ dcmtkpp::Response const message(1234, STATUS_Pending);
+
+ BOOST_CHECK_EQUAL(message.get_message_id_being_responded_to(), 1234);
+ BOOST_CHECK_EQUAL(message.get_status(), STATUS_Pending);
+}
+
+BOOST_AUTO_TEST_CASE(MessageConstructor)
+{
+ dcmtkpp::DataSet command_set;
+ command_set.add("MessageIDBeingRespondedTo", {1234});
+ command_set.add("Status", {STATUS_Pending});
+ dcmtkpp::Message const generic_message(command_set);
+
+ dcmtkpp::Response const message(generic_message);
+
+ BOOST_CHECK_EQUAL(message.get_message_id_being_responded_to(), 1234);
+ BOOST_CHECK_EQUAL(message.get_status(), STATUS_Pending);
+ BOOST_CHECK(!message.has_data_set());
+}
diff --git a/tests/code/SCU.cpp b/tests/code/SCU.cpp
new file mode 100644
index 0000000..58a1951
--- /dev/null
+++ b/tests/code/SCU.cpp
@@ -0,0 +1,41 @@
+#define BOOST_TEST_MODULE SCU
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/SCU.h"
+
+#include "../PeerFixtureBase.h"
+
+struct Fixture: public PeerFixtureBase
+{
+ Fixture()
+ : PeerFixtureBase(NET_REQUESTOR, 104, 10,
+ {
+ { UID_VerificationSOPClass,
+ {UID_LittleEndianImplicitTransferSyntax}
+ }
+ })
+ {
+ // Nothing else
+ }
+};
+
+BOOST_AUTO_TEST_CASE(DefaultConstructor)
+{
+ dcmtkpp::SCU const scu;
+ BOOST_CHECK_EQUAL(scu.get_affected_sop_class(), "");
+}
+
+BOOST_AUTO_TEST_CASE(AffectedSOPClassUID)
+{
+ dcmtkpp::SCU scu;
+ scu.set_affected_sop_class("1.2.3");
+ BOOST_CHECK_EQUAL(scu.get_affected_sop_class(), "1.2.3");
+}
+
+BOOST_FIXTURE_TEST_CASE(Echo, Fixture)
+{
+ dcmtkpp::SCU scu;
+ scu.set_network(&this->network);
+ scu.set_association(&this->association);
+ scu.echo();
+}
diff --git a/tests/code/ServiceRole.cpp b/tests/code/ServiceRole.cpp
new file mode 100644
index 0000000..609e244
--- /dev/null
+++ b/tests/code/ServiceRole.cpp
@@ -0,0 +1,62 @@
+#define BOOST_TEST_MODULE ServiceRole
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/Association.h"
+#include "dcmtkpp/Network.h"
+#include "dcmtkpp/ServiceRole.h"
+
+BOOST_AUTO_TEST_CASE(DefaultConstructor)
+{
+ dcmtkpp::ServiceRole const role;
+ BOOST_CHECK_EQUAL(
+ role.get_network(), static_cast<dcmtkpp::Network *>(NULL));
+ BOOST_CHECK_EQUAL(
+ role.get_association(), static_cast<dcmtkpp::Association *>(NULL));
+}
+
+BOOST_AUTO_TEST_CASE(Network)
+{
+ dcmtkpp::ServiceRole role;
+
+ dcmtkpp::Network network;
+ role.set_network(&network);
+
+ BOOST_CHECK_EQUAL(role.get_network(), &network);
+}
+
+BOOST_AUTO_TEST_CASE(Association)
+{
+ dcmtkpp::ServiceRole role;
+
+ dcmtkpp::Association association;
+ role.set_association(&association);
+
+ BOOST_CHECK_EQUAL(role.get_association(), &association);
+}
+
+BOOST_AUTO_TEST_CASE(CopyConstructor)
+{
+ dcmtkpp::Network network;
+ dcmtkpp::Association association;
+ dcmtkpp::ServiceRole role;
+ role.set_network(&network);
+ role.set_association(&association);
+
+ dcmtkpp::ServiceRole const other(role);
+ BOOST_CHECK_EQUAL(other.get_network(), role.get_network());
+ BOOST_CHECK_EQUAL(other.get_association(), role.get_association());
+}
+
+BOOST_AUTO_TEST_CASE(Assignement)
+{
+ dcmtkpp::Network network;
+ dcmtkpp::Association association;
+ dcmtkpp::ServiceRole role;
+ role.set_network(&network);
+ role.set_association(&association);
+
+ dcmtkpp::ServiceRole other;
+ other = role;
+ BOOST_CHECK_EQUAL(other.get_network(), role.get_network());
+ BOOST_CHECK_EQUAL(other.get_association(), role.get_association());
+}
diff --git a/tests/code/StoreSCU.cpp b/tests/code/StoreSCU.cpp
new file mode 100644
index 0000000..d1de26a
--- /dev/null
+++ b/tests/code/StoreSCU.cpp
@@ -0,0 +1,79 @@
+#define BOOST_TEST_MODULE StoreSCU
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/StoreSCU.h"
+
+#include "../PeerFixtureBase.h"
+
+struct Fixture: public PeerFixtureBase
+{
+ static bool called;
+
+ dcmtkpp::DataSet dataset;
+
+ Fixture()
+ : PeerFixtureBase(NET_REQUESTOR, 104, 10,
+ {
+ { UID_RawDataStorage,
+ {UID_LittleEndianImplicitTransferSyntax}
+ }
+ })
+ {
+ Fixture::called = false;
+
+ this->dataset.add("ImageType", {"ORIGINAL", "PRIMARY", "OTHER"});
+ this->dataset.add("PatientID", {"1234"});
+ this->dataset.add("StudyInstanceUID", {"2.25.386726390606491051215227596277040710"});
+ this->dataset.add("SeriesInstanceUID", {"2.25.235367796740370588607388995952651763168"});
+ this->dataset.add("SOPClassUID", {UID_RawDataStorage});
+ this->dataset.add("SOPInstanceUID", {"2.25.294312554735929033890522327215919068328"});
+ }
+
+
+ static void callback(void*, unsigned long)
+ {
+ Fixture::called = true;
+ }
+};
+
+bool Fixture::called = false;
+
+BOOST_AUTO_TEST_CASE(AffectedSOPClassUID)
+{
+ dcmtkpp::DataSet dataset;
+ dataset.add("SOPClassUID", {UID_RawDataStorage});
+
+ dcmtkpp::StoreSCU scu;
+ scu.set_affected_sop_class(dataset);
+ BOOST_CHECK_EQUAL(scu.get_affected_sop_class(), UID_RawDataStorage);
+}
+
+BOOST_AUTO_TEST_CASE(AffectedSOPClassUIDNoSOPClassUID)
+{
+ dcmtkpp::DataSet dataset;
+
+ dcmtkpp::StoreSCU scu;
+ BOOST_CHECK_THROW(scu.set_affected_sop_class(dataset), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(AffectedSOPClassUIDUnknownSOPClassUID)
+{
+ dcmtkpp::DataSet dataset;
+ dataset.add("SOPClassUID", {"invalid"});
+
+ dcmtkpp::StoreSCU scu;
+ BOOST_CHECK_THROW(scu.set_affected_sop_class(dataset), dcmtkpp::Exception);
+}
+
+BOOST_FIXTURE_TEST_CASE(Store, Fixture)
+{
+ dcmtkpp::StoreSCU scu;
+ scu.set_network(&this->network);
+ scu.set_association(&this->association);
+
+ scu.set_affected_sop_class(this->dataset);
+ scu.store(this->dataset, Fixture::callback);
+ BOOST_CHECK(this->called);
+}
diff --git a/tests/code/Tag.cpp b/tests/code/Tag.cpp
new file mode 100644
index 0000000..6c4e4a7
--- /dev/null
+++ b/tests/code/Tag.cpp
@@ -0,0 +1,187 @@
+#define BOOST_TEST_MODULE Tag
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/Tag.h"
+
+BOOST_AUTO_TEST_CASE(TwoArgumentsConstructor)
+{
+ dcmtkpp::Tag const tag(0xdead, 0xbeef);
+ BOOST_CHECK_EQUAL(tag.group, 0xdead);
+ BOOST_CHECK_EQUAL(tag.element, 0xbeef);
+}
+
+BOOST_AUTO_TEST_CASE(OneArgumentConstructor)
+{
+ dcmtkpp::Tag const tag(0xdeadbeef);
+ BOOST_CHECK_EQUAL(tag.group, 0xdead);
+ BOOST_CHECK_EQUAL(tag.element, 0xbeef);
+}
+
+BOOST_AUTO_TEST_CASE(StringConstructor)
+{
+ dcmtkpp::Tag const tag(std::string("PixelData"));
+ BOOST_CHECK_EQUAL(tag.group, 0x7fe0);
+ BOOST_CHECK_EQUAL(tag.element, 0x0010);
+}
+
+BOOST_AUTO_TEST_CASE(CharConstructor)
+{
+ dcmtkpp::Tag const tag("PixelData");
+ BOOST_CHECK_EQUAL(tag.group, 0x7fe0);
+ BOOST_CHECK_EQUAL(tag.element, 0x0010);
+}
+
+BOOST_AUTO_TEST_CASE(StringConstructorNumeric)
+{
+ dcmtkpp::Tag const tag(std::string("7fe00010"));
+ BOOST_CHECK_EQUAL(tag.group, 0x7fe0);
+ BOOST_CHECK_EQUAL(tag.element, 0x0010);
+}
+
+BOOST_AUTO_TEST_CASE(CharConstructorNumeric)
+{
+ dcmtkpp::Tag const tag("7fe00010");
+ BOOST_CHECK_EQUAL(tag.group, 0x7fe0);
+ BOOST_CHECK_EQUAL(tag.element, 0x0010);
+}
+
+BOOST_AUTO_TEST_CASE(StringConstructorWrong)
+{
+ BOOST_CHECK_THROW(dcmtkpp::Tag(std::string("Foobar")), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(CharConstructorWrong)
+{
+ BOOST_CHECK_THROW(dcmtkpp::Tag("Foobar"), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(StringConstructorNumericWrong)
+{
+ BOOST_CHECK_THROW(dcmtkpp::Tag(std::string("XXXXYYYY")), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(CharConstructorNumericWrong)
+{
+ BOOST_CHECK_THROW(dcmtkpp::Tag("XXXXYYYY"), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(CopyConstructor)
+{
+ dcmtkpp::Tag const tag(0xdead, 0xbeef);
+ dcmtkpp::Tag const other(tag);
+ BOOST_CHECK_EQUAL(other.group, 0xdead);
+ BOOST_CHECK_EQUAL(other.element, 0xbeef);
+}
+
+BOOST_AUTO_TEST_CASE(IsPrivate)
+{
+ dcmtkpp::Tag const tag1(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag2(0x7fe0, 0x0010);
+
+ BOOST_CHECK(tag1.is_private());
+ BOOST_CHECK(!tag2.is_private());
+}
+
+BOOST_AUTO_TEST_CASE(Name)
+{
+ dcmtkpp::Tag const tag(0x7fe0, 0x0010);
+ std::string const name = tag.get_name();
+ BOOST_CHECK_EQUAL(name, "PixelData");
+}
+
+BOOST_AUTO_TEST_CASE(NameWrong)
+{
+ dcmtkpp::Tag const tag(0xEEEE, 0xEEEE);
+ BOOST_CHECK_THROW(tag.get_name(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Equality)
+{
+ dcmtkpp::Tag const tag1(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag2(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag3(0xbeef, 0xf00d);
+
+ BOOST_CHECK(tag1 == tag2);
+ BOOST_CHECK( ! (tag1 == tag3) );
+}
+
+BOOST_AUTO_TEST_CASE(Difference)
+{
+ dcmtkpp::Tag const tag1(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag2(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag3(0xbeef, 0xf00d);
+
+ BOOST_CHECK( ! (tag1 != tag2) );
+ BOOST_CHECK(tag1 != tag3);
+}
+
+BOOST_AUTO_TEST_CASE(Inferior)
+{
+ dcmtkpp::Tag const tag1(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag2(0xdead, 0xf00d);
+ dcmtkpp::Tag const tag3(0xbeef, 0xf00d);
+
+ BOOST_CHECK(tag1 < tag2);
+ BOOST_CHECK(tag3 < tag1);
+
+ BOOST_CHECK( ! (tag2 < tag1) );
+ BOOST_CHECK( ! (tag1 < tag3) );
+}
+
+BOOST_AUTO_TEST_CASE(Superior)
+{
+ dcmtkpp::Tag const tag1(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag2(0xdead, 0xf00d);
+ dcmtkpp::Tag const tag3(0xbeef, 0xf00d);
+
+ BOOST_CHECK(tag2 > tag1);
+ BOOST_CHECK(tag1 > tag3);
+
+ BOOST_CHECK( ! (tag1 > tag2) );
+ BOOST_CHECK( ! (tag3 > tag1) );
+}
+
+BOOST_AUTO_TEST_CASE(InferiorOrEqual)
+{
+ dcmtkpp::Tag const tag1(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag2(0xdead, 0xf00d);
+ dcmtkpp::Tag const tag3(0xbeef, 0xf00d);
+ dcmtkpp::Tag const tag4(0xdead, 0xbeef);
+
+ BOOST_CHECK(tag1 <= tag2);
+ BOOST_CHECK(tag3 <= tag1);
+ BOOST_CHECK(tag1 <= tag4);
+
+ BOOST_CHECK( ! (tag2 <= tag1) );
+ BOOST_CHECK( ! (tag1 <= tag3) );
+}
+
+BOOST_AUTO_TEST_CASE(SuperiorOrEqual)
+{
+ dcmtkpp::Tag const tag1(0xdead, 0xbeef);
+ dcmtkpp::Tag const tag2(0xdead, 0xf00d);
+ dcmtkpp::Tag const tag3(0xbeef, 0xf00d);
+ dcmtkpp::Tag const tag4(0xdead, 0xbeef);
+
+ BOOST_CHECK(tag2 >= tag1);
+ BOOST_CHECK(tag1 >= tag3);
+ BOOST_CHECK(tag1 >= tag4);
+
+ BOOST_CHECK( ! (tag1 >= tag2) );
+ BOOST_CHECK( ! (tag3 >= tag1) );
+}
+
+BOOST_AUTO_TEST_CASE(StreamInsertion)
+{
+ dcmtkpp::Tag const tag(0xdead, 0xbeef);
+ std::ostringstream stream;
+ stream << tag;
+ BOOST_CHECK_EQUAL(stream.str(), "deadbeef");
+}
+
+BOOST_AUTO_TEST_CASE(StringConversion)
+{
+ dcmtkpp::Tag const tag(0xdead, 0xbeef);
+ BOOST_CHECK_EQUAL(std::string(tag), "deadbeef");
+}
diff --git a/tests/code/VR.cpp b/tests/code/VR.cpp
new file mode 100644
index 0000000..f231879
--- /dev/null
+++ b/tests/code/VR.cpp
@@ -0,0 +1,31 @@
+#define BOOST_TEST_MODULE VR
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/Exception.h"
+#include "dcmtkpp/VR.h"
+
+BOOST_AUTO_TEST_CASE(as_string)
+{
+ dcmtkpp::VR const vr(dcmtkpp::VR::AT);
+ std::string const string = dcmtkpp::as_string(vr);
+ BOOST_CHECK_EQUAL(string, "AT");
+}
+
+BOOST_AUTO_TEST_CASE(as_string_invalid)
+{
+ dcmtkpp::VR const vr(dcmtkpp::VR::INVALID);
+ BOOST_CHECK_THROW(dcmtkpp::as_string(vr), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(as_vr)
+{
+ std::string const string("AT");
+ dcmtkpp::VR const vr = dcmtkpp::as_vr(string);
+ BOOST_CHECK(vr == dcmtkpp::VR::AT);
+}
+
+BOOST_AUTO_TEST_CASE(as_vr_wrong)
+{
+ std::string const string("XX");
+ BOOST_CHECK_THROW(dcmtkpp::as_vr(string), dcmtkpp::Exception);
+}
diff --git a/tests/code/Value.cpp b/tests/code/Value.cpp
new file mode 100644
index 0000000..d62017a
--- /dev/null
+++ b/tests/code/Value.cpp
@@ -0,0 +1,250 @@
+#define BOOST_TEST_MODULE Value
+#include <boost/test/unit_test.hpp>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Element.h"
+#include "dcmtkpp/Exception.h"
+
+BOOST_AUTO_TEST_CASE(Empty)
+{
+ dcmtkpp::Value const value;
+
+ BOOST_CHECK(value.get_type() == dcmtkpp::Value::Type::Empty);
+ BOOST_CHECK_THROW(value.as_integers(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_reals(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_strings(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_data_sets(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(Integers)
+{
+ dcmtkpp::Value const value({1234});
+
+ BOOST_CHECK(value.get_type() == dcmtkpp::Value::Type::Integers);
+ BOOST_CHECK(value.as_integers() == dcmtkpp::Value::Integers({1234}));
+
+ BOOST_CHECK_THROW(value.as_reals(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_strings(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_data_sets(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(ModifyIntegers)
+{
+ dcmtkpp::Value value({1234});
+ value.as_integers().push_back(5678);
+ BOOST_CHECK(value.as_integers() == dcmtkpp::Value::Integers({1234, 5678}));
+}
+
+BOOST_AUTO_TEST_CASE(Reals)
+{
+ dcmtkpp::Value const value({12.34});
+
+ BOOST_CHECK(value.get_type() == dcmtkpp::Value::Type::Reals);
+ BOOST_CHECK(value.as_reals() == dcmtkpp::Value::Reals({12.34}));
+
+ BOOST_CHECK_THROW(value.as_integers(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_strings(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_data_sets(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(ModifyReals)
+{
+ dcmtkpp::Value value({12.34});
+ value.as_reals().push_back(56.78);
+ BOOST_CHECK(value.as_reals() == dcmtkpp::Value::Reals({12.34, 56.78}));
+}
+
+BOOST_AUTO_TEST_CASE(Strings)
+{
+ dcmtkpp::Value const value({"foo"});
+
+ BOOST_CHECK(value.get_type() == dcmtkpp::Value::Type::Strings);
+ BOOST_CHECK(value.as_strings() == dcmtkpp::Value::Strings({"foo"}));
+
+ BOOST_CHECK_THROW(value.as_integers(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_reals(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_data_sets(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(ModifyStrings)
+{
+ dcmtkpp::Value value({"foo"});
+ value.as_strings().push_back("bar");
+ BOOST_CHECK(value.as_strings() == dcmtkpp::Value::Strings({"foo", "bar"}));
+}
+
+BOOST_AUTO_TEST_CASE(DataSets)
+{
+ dcmtkpp::DataSet data_set;
+ data_set.add("PatientID", {"DJ1234"});
+ dcmtkpp::Value const value({data_set});
+
+ BOOST_CHECK(value.get_type() == dcmtkpp::Value::Type::DataSets);
+ BOOST_CHECK_EQUAL(value.as_data_sets().size(), 1);
+ BOOST_CHECK(value.as_data_sets()[0].has("PatientID"));
+ BOOST_CHECK(
+ value.as_data_sets()[0].as_string("PatientID") ==
+ dcmtkpp::Value::Strings({"DJ1234"}));
+
+ BOOST_CHECK_THROW(value.as_integers(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_strings(), dcmtkpp::Exception);
+ BOOST_CHECK_THROW(value.as_reals(), dcmtkpp::Exception);
+}
+
+BOOST_AUTO_TEST_CASE(ModifyDataSets)
+{
+ dcmtkpp::DataSet data_set;
+ data_set.add("PatientID");
+ data_set.as_string("PatientID").push_back("DJ1234");
+ dcmtkpp::Value value({data_set});
+
+ value.as_data_sets()[0].as_string("PatientID")[0] = "XXX";
+
+ BOOST_CHECK(value.get_type() == dcmtkpp::Value::Type::DataSets);
+ BOOST_CHECK_EQUAL(value.as_data_sets().size(), 1);
+ BOOST_CHECK(value.as_data_sets()[0].has("PatientID"));
+ BOOST_CHECK(
+ value.as_data_sets()[0].as_string("PatientID") ==
+ dcmtkpp::Value::Strings({"XXX"}));
+}
+
+BOOST_AUTO_TEST_CASE(EqualityEmpty)
+{
+ dcmtkpp::Value const value1;
+ dcmtkpp::Value const value2;
+ dcmtkpp::Value const value3((dcmtkpp::Value::Integers()));
+ BOOST_CHECK(value1 == value2);
+ BOOST_CHECK( ! (value1 == value3));
+}
+
+BOOST_AUTO_TEST_CASE(EqualityIntegers)
+{
+ dcmtkpp::Value const value1({1,2});
+ dcmtkpp::Value const value2({1,2});
+ dcmtkpp::Value const value3({3,4});
+ dcmtkpp::Value const value4({3,4});
+ BOOST_CHECK(value1 == value2);
+ BOOST_CHECK( ! (value1 == value3));
+ BOOST_CHECK( ! (value1 == value4));
+}
+
+BOOST_AUTO_TEST_CASE(EqualityReals)
+{
+ dcmtkpp::Value const value1({1,2});
+ dcmtkpp::Value const value2({1,2});
+ dcmtkpp::Value const value3({3,4});
+ dcmtkpp::Value const value4({3,4});
+ BOOST_CHECK(value1 == value2);
+ BOOST_CHECK( ! (value1 == value3));
+ BOOST_CHECK( ! (value1 == value4));
+}
+
+BOOST_AUTO_TEST_CASE(EqualityStrings)
+{
+ dcmtkpp::Value const value1({"1","2"});
+ dcmtkpp::Value const value2({"1","2"});
+ dcmtkpp::Value const value3({"3","4"});
+ dcmtkpp::Value const value4({3,4});
+ BOOST_CHECK(value1 == value2);
+ BOOST_CHECK( ! (value1 == value3));
+ BOOST_CHECK( ! (value1 == value4));
+}
+
+BOOST_AUTO_TEST_CASE(EqualityDataSets)
+{
+ dcmtkpp::DataSet dataset1;
+ dataset1.add("PatientID", {"DJ1234"});
+ dataset1.add("PixelSpacing", {1.5, 2.5});
+
+ dcmtkpp::DataSet dataset2;
+ dataset1.add("PatientName", {"Doe^John"});
+ dataset1.add("PatientAge", {"042Y"});
+
+ dcmtkpp::Value const value1({dataset1});
+ dcmtkpp::Value const value2({dataset1});
+ dcmtkpp::Value const value3({dataset2});
+ dcmtkpp::Value const value4({3,4});
+ BOOST_CHECK(value1 == value2);
+ BOOST_CHECK( ! (value1 == value3));
+ BOOST_CHECK( ! (value1 == value4));
+}
+
+BOOST_AUTO_TEST_CASE(DifferenceEmpty)
+{
+ dcmtkpp::Value const value1;
+ dcmtkpp::Value const value2;
+ dcmtkpp::Value const value3((dcmtkpp::Value::Integers()));
+ BOOST_CHECK(! (value1 != value2));
+ BOOST_CHECK(value1 != value3);
+}
+
+BOOST_AUTO_TEST_CASE(DifferenceIntegers)
+{
+ dcmtkpp::Value const value1({1,2});
+ dcmtkpp::Value const value2({1,2});
+ dcmtkpp::Value const value3({3,4});
+ dcmtkpp::Value const value4({3,4});
+ BOOST_CHECK(! (value1 != value2));
+ BOOST_CHECK(value1 != value3);
+ BOOST_CHECK(value1 != value4);
+}
+
+BOOST_AUTO_TEST_CASE(DifferenceReals)
+{
+ dcmtkpp::Value const value1({1.,2.});
+ dcmtkpp::Value const value2({1.,2.});
+ dcmtkpp::Value const value3({3.,4.});
+ dcmtkpp::Value const value4({3,4});
+ BOOST_CHECK(! (value1 != value2));
+ BOOST_CHECK(value1 != value3);
+ BOOST_CHECK(value1 != value4);
+}
+
+BOOST_AUTO_TEST_CASE(DifferenceStrings)
+{
+ dcmtkpp::Value const value1({"1","2"});
+ dcmtkpp::Value const value2({"1","2"});
+ dcmtkpp::Value const value3({"3","4"});
+ dcmtkpp::Value const value4({3,4});
+ BOOST_CHECK(! (value1 != value2));
+ BOOST_CHECK(value1 != value3);
+ BOOST_CHECK(value1 != value4);
+}
+
+BOOST_AUTO_TEST_CASE(DifferenceDataSets)
+{
+ dcmtkpp::DataSet dataset1;
+ dataset1.add("PatientID", {"DJ1234"});
+ dataset1.add("PixelSpacing", {1.5, 2.5});
+
+ dcmtkpp::DataSet dataset2;
+ dataset1.add("PatientName", {"Doe^John"});
+ dataset1.add("PatientAge", {"042Y"});
+
+ dcmtkpp::Value const value1({dataset1});
+ dcmtkpp::Value const value2({dataset1});
+ dcmtkpp::Value const value3({dataset2});
+ dcmtkpp::Value const value4({3,4});
+ BOOST_CHECK(! (value1 != value2));
+ BOOST_CHECK(value1 != value3);
+ BOOST_CHECK(value1 != value4);
+}
+
+struct Visitor
+{
+ typedef bool result_type;
+
+ template<typename T>
+ bool operator()(T const & container) const
+ {
+ return true;
+ }
+};
+
+BOOST_AUTO_TEST_CASE(VisitorEmpty)
+{
+ dcmtkpp::Value const value;
+ BOOST_CHECK_THROW(
+ dcmtkpp::apply_visitor(Visitor(), value),
+ dcmtkpp::Exception);
+}
diff --git a/tests/code/conversion.cpp b/tests/code/conversion.cpp
new file mode 100644
index 0000000..ce4c671
--- /dev/null
+++ b/tests/code/conversion.cpp
@@ -0,0 +1,424 @@
+#define BOOST_TEST_MODULE conversion
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dctk.h>
+
+#include "dcmtkpp/conversion.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/ElementAccessor.h"
+#include "dcmtkpp/Tag.h"
+#include "dcmtkpp/Value.h"
+#include "dcmtkpp/VR.h"
+#include "dcmtkpp/VRTraits.h"
+
+BOOST_AUTO_TEST_CASE(TagFromDcmtkpp)
+{
+ dcmtkpp::Tag const source(0xdead, 0xbeef);
+ DcmTagKey const destination = dcmtkpp::convert(source);
+
+ BOOST_CHECK_EQUAL(destination.getGroup(), 0xdead);
+ BOOST_CHECK_EQUAL(destination.getElement(), 0xbeef);
+}
+
+BOOST_AUTO_TEST_CASE(TagFromDcmtk)
+{
+ DcmTagKey const source(0xdead, 0xbeef);
+ dcmtkpp::Tag const destination = dcmtkpp::convert(source);
+
+ BOOST_CHECK_EQUAL(destination.group, 0xdead);
+ BOOST_CHECK_EQUAL(destination.element, 0xbeef);
+}
+
+template<typename TValueType>
+void compare(TValueType const & t1, TValueType const & t2)
+{
+ BOOST_CHECK_EQUAL(t1, t2);
+}
+
+template<>
+void compare<dcmtkpp::Value::Reals::value_type>(
+ dcmtkpp::Value::Reals::value_type const & t1,
+ dcmtkpp::Value::Reals::value_type const & t2)
+{
+ BOOST_CHECK_CLOSE(t1, t2, 1e-6);
+}
+
+template<dcmtkpp::VR VVR, DcmEVR VEVR, typename TInputType, typename TOutputType>
+void test_element_from_dcmtkpp(
+ TInputType const & source_value,
+ TInputType const & (dcmtkpp::Element::*getter)() const)
+{
+ dcmtkpp::Tag const source_tag(0xdead, 0xbeef);
+ DcmTagKey const destination_tag = dcmtkpp::convert(source_tag);
+
+ dcmtkpp::Element const source(source_value, VVR);
+
+ DcmElement * destination = dcmtkpp::convert(source_tag, source);
+ BOOST_CHECK_NE(destination, (DcmElement const *)(NULL));
+
+ BOOST_CHECK_EQUAL(destination->getVR(), VEVR);
+ BOOST_CHECK_NE(
+ dynamic_cast<TOutputType *>(destination), (TOutputType *)(NULL));
+
+ BOOST_CHECK_EQUAL(destination->getVM(), source.size());
+ for(std::size_t i=0; i<source.size(); ++i)
+ {
+ typedef typename dcmtkpp::VRTraits<VEVR>::ValueType ValueType;
+ if(typeid(TInputType) == typeid(dcmtkpp::Value::Reals))
+ {
+ compare<ValueType>(
+ dcmtkpp::ElementAccessor<ValueType>::element_get(*destination, i),
+ (source.*getter)()[i]);
+ }
+ else
+ {
+ BOOST_CHECK_EQUAL(
+ dcmtkpp::ElementAccessor<ValueType>::element_get(*destination, i),
+ (source.*getter)()[i]);
+ }
+ }
+}
+
+template<dcmtkpp::VR VVR, DcmEVR VEVR, typename TInputType, typename TElementType>
+void test_element_to_dcmtkpp(
+ TInputType const & source_value,
+ TInputType const & (dcmtkpp::Element::*getter)() const)
+{
+ DcmTag const source_tag(0xdead, 0xbeef, VEVR);
+ TElementType source(source_tag);
+ if(typeid(TInputType) == typeid(dcmtkpp::Value::Strings) ||
+ VEVR == EVR_IS || VEVR == EVR_DS)
+ {
+ OFString value;
+
+ if(!source_value.empty())
+ {
+ auto const last_it = --source_value.end();
+ auto it = source_value.begin();
+ while(it != last_it)
+ {
+ std::ostringstream stream;
+ stream << *it;
+ value += stream.str().c_str();
+ value += "\\";
+ ++it;
+ }
+
+ std::ostringstream stream;
+ stream << *last_it;
+ value += stream.str().c_str();
+ }
+
+ source.putOFStringArray(value);
+ }
+ else
+ {
+ for(unsigned int i=0; i<source_value.size(); ++i)
+ {
+ auto const & item = source_value[i];
+ dcmtkpp::ElementAccessor<typename dcmtkpp::VRTraits<VEVR>::ValueType>::element_set(
+ source, item, i);
+ }
+ }
+
+ dcmtkpp::Element const destination = dcmtkpp::convert(&source);
+
+ BOOST_CHECK(VVR == destination.vr);
+ BOOST_CHECK_EQUAL(source.getVM(), destination.size());
+ for(std::size_t i=0; i<destination.size(); ++i)
+ {
+ typedef typename dcmtkpp::VRTraits<VEVR>::ValueType ValueType;
+ if(typeid(TInputType) == typeid(dcmtkpp::Value::Reals))
+ {
+ compare<ValueType>(
+ dcmtkpp::ElementAccessor<ValueType>::element_get(source, i),
+ (destination.*getter)()[i]);
+ }
+ else
+ {
+ BOOST_CHECK_EQUAL(
+ dcmtkpp::ElementAccessor<ValueType>::element_get(source, i),
+ (destination.*getter)()[i]);
+ }
+ }
+}
+
+#define ElementTest(vr, InputType, ElementType, value, getter) \
+BOOST_AUTO_TEST_CASE(vr##FromDcmtkpp) \
+{ \
+ test_element_from_dcmtkpp< \
+ dcmtkpp::VR::vr, EVR_##vr, InputType, ElementType>(value, getter); \
+} \
+BOOST_AUTO_TEST_CASE(vr##ToDcmtkpp) \
+{ \
+ test_element_to_dcmtkpp< \
+ dcmtkpp::VR::vr, EVR_##vr, InputType, ElementType>(value, getter); \
+}
+
+ElementTest(
+ AE, dcmtkpp::Value::Strings, DcmApplicationEntity,
+ dcmtkpp::Value::Strings({"foo", "bar"}), &dcmtkpp::Element::as_string);
+
+ElementTest(
+ AS, dcmtkpp::Value::Strings, DcmAgeString,
+ dcmtkpp::Value::Strings({"012Y", "345D"}), &dcmtkpp::Element::as_string);
+
+ElementTest(
+ CS, dcmtkpp::Value::Strings, DcmCodeString,
+ dcmtkpp::Value::Strings({"foo", "bar"}), &dcmtkpp::Element::as_string);
+
+ElementTest(
+ DA, dcmtkpp::Value::Strings, DcmDate,
+ dcmtkpp::Value::Strings({"19000101", "20131215"}),
+ &dcmtkpp::Element::as_string);
+
+ElementTest(
+ DS, dcmtkpp::Value::Reals, DcmDecimalString,
+ dcmtkpp::Value::Reals({12.34, 56.78}), &dcmtkpp::Element::as_real);
+
+ElementTest(
+ DT, dcmtkpp::Value::Strings, DcmDateTime,
+ dcmtkpp::Value::Strings({"19000101123456", "201312150123"}),
+ &dcmtkpp::Element::as_string);
+
+ElementTest(
+ FL, dcmtkpp::Value::Reals, DcmFloatingPointSingle,
+ dcmtkpp::Value::Reals({12.34, 56.78}), &dcmtkpp::Element::as_real);
+
+ElementTest(
+ FD, dcmtkpp::Value::Reals, DcmFloatingPointDouble,
+ dcmtkpp::Value::Reals({12.34, 56.78}), &dcmtkpp::Element::as_real);
+
+ElementTest(
+ IS, dcmtkpp::Value::Integers, DcmIntegerString,
+ dcmtkpp::Value::Integers({34567, -67890}), &dcmtkpp::Element::as_int);
+
+ElementTest(
+ LO, dcmtkpp::Value::Strings, DcmLongString,
+ dcmtkpp::Value::Strings({"foo bar", "something else"}),
+ &dcmtkpp::Element::as_string);
+
+ElementTest(
+ LT, dcmtkpp::Value::Strings, DcmLongText,
+ dcmtkpp::Value::Strings({"foo\nbar\\something else"}),
+ &dcmtkpp::Element::as_string);
+
+// OB
+// OF
+// OW
+
+ElementTest(
+ PN, dcmtkpp::Value::Strings, DcmPersonName,
+ dcmtkpp::Value::Strings({"Doe^John", "^Bob^Dr."}),
+ &dcmtkpp::Element::as_string);
+
+ElementTest(
+ SH, dcmtkpp::Value::Strings, DcmShortString,
+ dcmtkpp::Value::Strings({"foo", "bar"}), &dcmtkpp::Element::as_string);
+
+ElementTest(
+ SL, dcmtkpp::Value::Integers, DcmSignedLong,
+ dcmtkpp::Value::Integers({34567, -56789}), &dcmtkpp::Element::as_int);
+
+ElementTest(
+ SS, dcmtkpp::Value::Integers, DcmSignedShort,
+ dcmtkpp::Value::Integers({1234, -5678}), &dcmtkpp::Element::as_int);
+
+ElementTest(
+ ST, dcmtkpp::Value::Strings, DcmShortText,
+ dcmtkpp::Value::Strings({"foo\nbar\\something else"}),
+ &dcmtkpp::Element::as_string);
+
+ElementTest(
+ TM, dcmtkpp::Value::Strings, DcmTime,
+ dcmtkpp::Value::Strings({"123456", "0123"}),
+ &dcmtkpp::Element::as_string);
+
+ElementTest(
+ UI, dcmtkpp::Value::Strings, DcmUniqueIdentifier,
+ dcmtkpp::Value::Strings(
+ {"1.2.840.10008.5.1.4.1.1.4", "1.2.840.10008.5.1.4.1.1.4.1"}),
+ &dcmtkpp::Element::as_string);
+
+ElementTest(
+ UL, dcmtkpp::Value::Integers, DcmUnsignedLong,
+ dcmtkpp::Value::Integers({123456, 789012}), &dcmtkpp::Element::as_int);
+
+// UN
+
+ElementTest(
+ US, dcmtkpp::Value::Integers, DcmUnsignedShort,
+ dcmtkpp::Value::Integers({12345, 6789}), &dcmtkpp::Element::as_int);
+
+ElementTest(
+ UT, dcmtkpp::Value::Strings, DcmUnlimitedText,
+ dcmtkpp::Value::Strings({"foo\nbar\\something else"}),
+ &dcmtkpp::Element::as_string);
+
+BOOST_AUTO_TEST_CASE(ATFromDcmtkpp)
+{
+ dcmtkpp::Element const source(
+ dcmtkpp::Value::Strings({"deadbeef", "beeff00d"}), dcmtkpp::VR::AT);
+
+ DcmElement * destination = dcmtkpp::convert(
+ dcmtkpp::Tag(0x1234, 0x5678), source);
+
+ BOOST_CHECK_NE(destination, (DcmElement const *)(NULL));
+
+ BOOST_CHECK_EQUAL(destination->getVR(), dcmtkpp::convert(source.vr));
+ BOOST_CHECK_NE(
+ dynamic_cast<DcmAttributeTag *>(destination),
+ (DcmAttributeTag *)(NULL));
+
+ BOOST_CHECK_EQUAL(destination->getVM(), source.size());
+ for(std::size_t i=0; i<source.size(); ++i)
+ {
+ dcmtkpp::Tag const & source_tag = source.as_string()[i];
+
+ DcmTagKey destination_tag;
+ OFCondition const condition = destination->getTagVal(destination_tag, i);
+ BOOST_CHECK(condition.good());
+
+ BOOST_CHECK(source_tag == dcmtkpp::convert(destination_tag));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(ATToDcmtkpp)
+{
+ DcmAttributeTag source(DcmTag(0x1234, 0x5678, EVR_AT));
+ source.putTagVal(DcmTagKey(0xdead, 0xbeef), 0);
+ source.putTagVal(DcmTagKey(0xbeef, 0xf00d), 1);
+
+ dcmtkpp::Element const destination = dcmtkpp::convert(&source);
+
+ BOOST_CHECK(destination.vr == dcmtkpp::convert(source.getVR()));
+ BOOST_CHECK_EQUAL(source.getVM(), destination.size());
+ for(std::size_t i=0; i<destination.size(); ++i)
+ {
+ DcmTagKey source_tag;
+ source.getTagVal(source_tag, i);
+
+ dcmtkpp::Tag const & destination_tag = destination.as_string()[i];
+ BOOST_CHECK(dcmtkpp::convert(source_tag) == destination_tag);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(SQFromDcmtkpp)
+{
+ dcmtkpp::DataSet item;
+ item.add("PatientID");
+ item.as_string("PatientID").push_back("DJ1234");
+
+ dcmtkpp::Element const source(
+ dcmtkpp::Value::DataSets({item}), dcmtkpp::VR::SQ);
+
+ dcmtkpp::Tag const source_tag(0xdead, 0xbeef);
+
+ DcmElement * destination = dcmtkpp::convert(source_tag, source);
+
+ BOOST_CHECK_NE(destination, (DcmElement const *)(NULL));
+
+ BOOST_CHECK_EQUAL(destination->getVR(), dcmtkpp::convert(source.vr));
+ BOOST_CHECK_NE(
+ dynamic_cast<DcmSequenceOfItems *>(destination),
+ (DcmSequenceOfItems *)(NULL));
+
+ BOOST_CHECK_EQUAL(destination->getVM(), source.size());
+ for(std::size_t i=0; i<source.size(); ++i)
+ {
+ dcmtkpp::DataSet const & source_item = source.as_data_set()[i];
+ DcmItem * item = dynamic_cast<DcmSequenceOfItems *>(destination)->getItem(i);
+ DcmDataset * destination_item = dynamic_cast<DcmDataset *>(item);
+ BOOST_CHECK(source_item == dcmtkpp::convert(destination_item));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(SQToDcmtkpp)
+{
+ DcmDataset * item = new DcmDataset;
+ item->putAndInsertOFStringArray(DCM_PatientID, "DJ1234");
+
+ DcmSequenceOfItems source(DcmTag(0xdead, 0xbeef, EVR_SQ));
+ source.append(item);
+
+ dcmtkpp::Element const destination = dcmtkpp::convert(&source);
+
+ BOOST_CHECK(destination.vr == dcmtkpp::convert(source.getVR()));
+ BOOST_CHECK_EQUAL(source.getVM(), destination.size());
+ for(std::size_t i=0; i<destination.size(); ++i)
+ {
+ DcmItem * item = source.getItem(i);
+ DcmDataset * source_item = dynamic_cast<DcmDataset *>(item);
+ BOOST_REQUIRE(source_item != NULL);
+
+ dcmtkpp::DataSet const & destination_item = destination.as_data_set()[i];
+ BOOST_CHECK(dcmtkpp::convert(source_item) == destination_item);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(EmptyDataSetFromDcmtkpp)
+{
+ dcmtkpp::DataSet empty;
+ DcmItem * result = dcmtkpp::convert(empty);
+ BOOST_CHECK_EQUAL(result->card(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(EmptyDataSetFromDcmtk)
+{
+ DcmDataset empty;
+ dcmtkpp::DataSet const result = dcmtkpp::convert(&empty);
+ BOOST_CHECK(result.empty());
+}
+
+BOOST_AUTO_TEST_CASE(DataSetFromDcmtkpp)
+{
+ dcmtkpp::Element const patient_id_source(
+ dcmtkpp::Value::Strings({"DJ1234"}), dcmtkpp::VR::CS);
+ dcmtkpp::Element const pixel_spacing_source(
+ dcmtkpp::Value::Reals({1.23, 4.56}), dcmtkpp::VR::DS);
+
+ dcmtkpp::DataSet source;
+ source.add(dcmtkpp::Tag("PatientID"), patient_id_source);
+ source.add(dcmtkpp::Tag("PixelSpacing"), pixel_spacing_source);
+
+ DcmItem * result = dcmtkpp::convert(source);
+ BOOST_CHECK_EQUAL(result->card(), 2);
+
+ DcmElement * patient_id;
+ OFCondition const patient_id_ok =
+ result->findAndGetElement(DCM_PatientID, patient_id);
+ BOOST_CHECK(patient_id_ok.good());
+ BOOST_CHECK(
+ dcmtkpp::convert(patient_id).as_string() ==
+ patient_id_source.as_string());
+
+ DcmElement * pixel_spacing;
+ OFCondition const pixel_spacing_ok =
+ result->findAndGetElement(DCM_PixelSpacing, pixel_spacing);
+ BOOST_CHECK(pixel_spacing_ok.good());
+ BOOST_CHECK(
+ dcmtkpp::convert(pixel_spacing).as_real() ==
+ pixel_spacing_source.as_real());
+}
+
+BOOST_AUTO_TEST_CASE(DataSetFromDcmtk)
+{
+ dcmtkpp::Element const patient_id_source(
+ dcmtkpp::Value::Strings({"DJ1234"}), dcmtkpp::VR::CS);
+ dcmtkpp::Element const pixel_spacing_source(
+ dcmtkpp::Value::Reals({1.23, 4.56}), dcmtkpp::VR::DS);
+
+ DcmDataset source;
+ source.insert(dcmtkpp::convert(dcmtkpp::Tag("PatientID"), patient_id_source));
+ source.insert(dcmtkpp::convert(dcmtkpp::Tag("PixelSpacing"), pixel_spacing_source));
+
+ dcmtkpp::DataSet const result = dcmtkpp::convert(&source);
+ BOOST_CHECK_EQUAL(result.size(), 2);
+ BOOST_CHECK(
+ result.as_string(dcmtkpp::Tag("PatientID")) ==
+ patient_id_source.as_string());
+ BOOST_CHECK(
+ result.as_real(dcmtkpp::Tag("PixelSpacing")) ==
+ pixel_spacing_source.as_real());
+}
diff --git a/tests/code/json_converter.cpp b/tests/code/json_converter.cpp
new file mode 100644
index 0000000..8e1200a
--- /dev/null
+++ b/tests/code/json_converter.cpp
@@ -0,0 +1,269 @@
+#define BOOST_TEST_MODULE json_converter
+#include <boost/test/unit_test.hpp>
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include <jsoncpp/json/json.h>
+
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/Element.h"
+#include "dcmtkpp/json_converter.h"
+#include "dcmtkpp/Value.h"
+#include "dcmtkpp/VR.h"
+
+BOOST_AUTO_TEST_CASE(AsJSONEmpty)
+{
+ dcmtkpp::DataSet data_set;
+ auto const json = dcmtkpp::as_json(data_set);
+ BOOST_REQUIRE(json.empty());
+}
+
+template<typename TChecker, typename TGetter, typename TValue>
+void check_json_array(
+ Json::Value const & object, TChecker checker, TGetter getter,
+ TValue const & expected)
+{
+ BOOST_REQUIRE(object.isArray());
+ BOOST_REQUIRE_EQUAL(object.size(), expected.size());
+ for(Json::ArrayIndex i=0; i<object.size(); ++i)
+ {
+ BOOST_REQUIRE((object[i].*checker)());
+ BOOST_REQUIRE_EQUAL((object[i].*getter)(), expected[i]);
+ }
+}
+
+void check_json_object(Json::Value const & object,
+ std::set<std::string> const & expected_members)
+{
+ BOOST_REQUIRE(object.isObject());
+ auto const members = object.getMemberNames();
+ BOOST_REQUIRE(
+ std::set<std::string>(members.begin(), members.end()) == expected_members);
+}
+
+void check_json_string(Json::Value const & object, std::string const & expected_value)
+{
+ BOOST_REQUIRE(object.isString());
+ BOOST_REQUIRE_EQUAL(object.asString(), expected_value);
+}
+
+BOOST_AUTO_TEST_CASE(AsJSONIntegers)
+{
+ dcmtkpp::DataSet data_set;
+ data_set.add(0xdeadbeef,
+ dcmtkpp::Element(dcmtkpp::Value::Integers({1, 2}), dcmtkpp::VR::SS));
+ auto const json = dcmtkpp::as_json(data_set);
+ check_json_object(json, {"deadbeef"});
+ check_json_object(json["deadbeef"], {"vr", "Value"});
+ check_json_string(json["deadbeef"]["vr"], "SS");
+ check_json_array(json["deadbeef"]["Value"],
+ &Json::Value::isInt, &Json::Value::asInt, data_set.as_int(0xdeadbeef));
+}
+
+BOOST_AUTO_TEST_CASE(AsJSONReals)
+{
+ dcmtkpp::DataSet data_set;
+ data_set.add(0xdeadbeef,
+ dcmtkpp::Element(dcmtkpp::Value::Reals({1.2, 3.4}), dcmtkpp::VR::FL));
+ auto const json = dcmtkpp::as_json(data_set);
+ check_json_object(json, {"deadbeef"});
+ check_json_object(json["deadbeef"], {"vr", "Value"});
+ check_json_string(json["deadbeef"]["vr"], "FL");
+ check_json_array(json["deadbeef"]["Value"],
+ &Json::Value::isDouble, &Json::Value::asDouble, data_set.as_real(0xdeadbeef));
+}
+
+BOOST_AUTO_TEST_CASE(AsJSONStrings)
+{
+ dcmtkpp::DataSet data_set;
+ data_set.add(0xdeadbeef,
+ dcmtkpp::Element(
+ dcmtkpp::Value::Strings({"FOO", "BAR"}),
+ dcmtkpp::VR::CS));
+ auto const json = dcmtkpp::as_json(data_set);
+ check_json_object(json, {"deadbeef"});
+ check_json_object(json["deadbeef"], {"vr", "Value"});
+ check_json_string(json["deadbeef"]["vr"], "CS");
+ check_json_array(json["deadbeef"]["Value"],
+ &Json::Value::isString, &Json::Value::asString, data_set.as_string(0xdeadbeef));
+}
+
+BOOST_AUTO_TEST_CASE(AsJSONPersonName)
+{
+ dcmtkpp::DataSet data_set;
+ data_set.add(0xdeadbeef,
+ dcmtkpp::Element(
+ dcmtkpp::Value::Strings({"Alpha^Betic=Ideo^Graphic=Pho^Netic"}),
+ dcmtkpp::VR::PN));
+ auto const json = dcmtkpp::as_json(data_set);
+ check_json_object(json, {"deadbeef"});
+ check_json_object(json["deadbeef"], {"vr", "Value"});
+ check_json_string(json["deadbeef"]["vr"], "PN");
+
+ BOOST_REQUIRE(json["deadbeef"]["Value"].isArray());
+ BOOST_REQUIRE_EQUAL(json["deadbeef"]["Value"].size(), 1);
+ check_json_object(
+ json["deadbeef"]["Value"][0], {"Alphabetic", "Ideographic", "Phonetic"});
+ check_json_string(json["deadbeef"]["Value"][0]["Alphabetic"], {"Alpha^Betic"});
+ check_json_string(json["deadbeef"]["Value"][0]["Ideographic"], {"Ideo^Graphic"});
+ check_json_string(json["deadbeef"]["Value"][0]["Phonetic"], {"Pho^Netic"});
+}
+
+BOOST_AUTO_TEST_CASE(AsJSONDataSets)
+{
+ dcmtkpp::DataSet item;
+ item.add(0xbeeff00d,
+ dcmtkpp::Element(dcmtkpp::Value::Integers({1,2}), dcmtkpp::VR::SS));
+ dcmtkpp::DataSet data_set;
+ data_set.add(0xdeadbeef,
+ dcmtkpp::Element(
+ dcmtkpp::Value::DataSets({item}),
+ dcmtkpp::VR::SQ));
+
+ auto const json = dcmtkpp::as_json(data_set);
+
+ check_json_object(json, {"deadbeef"});
+ check_json_object(json["deadbeef"], {"vr", "Value"});
+ check_json_string(json["deadbeef"]["vr"], "SQ");
+
+ BOOST_REQUIRE(json["deadbeef"]["Value"].isArray());
+ BOOST_REQUIRE_EQUAL(json["deadbeef"]["Value"].size(), 1);
+ check_json_object(json["deadbeef"]["Value"][0], {"beeff00d"});
+
+ check_json_object(json["deadbeef"]["Value"][0]["beeff00d"], {"vr", "Value"});
+ check_json_string(json["deadbeef"]["Value"][0]["beeff00d"]["vr"], "SS");
+ check_json_array(json["deadbeef"]["Value"][0]["beeff00d"]["Value"],
+ &Json::Value::isInt, &Json::Value::asInt, item.as_int(0xbeeff00d));
+}
+
+BOOST_AUTO_TEST_CASE(AsJSONBinary)
+{
+ dcmtkpp::DataSet data_set;
+ data_set.add(0xdeadbeef,
+ dcmtkpp::Element(
+ dcmtkpp::Value::Binary({0x1, 0x2, 0x3, 0x4, 0x5}),
+ dcmtkpp::VR::OB));
+
+ auto const json = dcmtkpp::as_json(data_set);
+
+ check_json_object(json, {"deadbeef"});
+ check_json_object(json["deadbeef"], {"vr", "InlineBinary"});
+ check_json_string(json["deadbeef"]["vr"], "OB");
+ check_json_string(json["deadbeef"]["InlineBinary"], "AQIDBAU=");
+}
+
+BOOST_AUTO_TEST_CASE(AsDataSetEmpty)
+{
+ std::stringstream data;
+ data << "{ }";
+ Json::Value json;
+ data >> json;
+
+ dcmtkpp::DataSet const data_set = dcmtkpp::as_dataset(json);
+ BOOST_REQUIRE(data_set.empty());
+}
+
+BOOST_AUTO_TEST_CASE(AsDataSetIntegers)
+{
+ std::stringstream data;
+ data << "{ \"deadbeef\": { \"vr\": \"SS\", \"Value\": [1, 2] } }";
+ Json::Value json;
+ data >> json;
+
+ dcmtkpp::DataSet const data_set = dcmtkpp::as_dataset(json);
+ BOOST_REQUIRE_EQUAL(data_set.size(), 1);
+ BOOST_REQUIRE(data_set.has("deadbeef"));
+ BOOST_REQUIRE(data_set.get_vr("deadbeef") == dcmtkpp::VR::SS);
+ BOOST_REQUIRE(data_set.is_int("deadbeef"));
+ BOOST_REQUIRE(data_set.as_int("deadbeef") == dcmtkpp::Value::Integers({1, 2}));
+}
+
+BOOST_AUTO_TEST_CASE(AsDataSetReals)
+{
+ std::stringstream data;
+ data << "{ \"deadbeef\": { \"vr\": \"FL\", \"Value\": [1.2, 3.4] } }";
+ Json::Value json;
+ data >> json;
+
+ dcmtkpp::DataSet const data_set = dcmtkpp::as_dataset(json);
+ BOOST_REQUIRE_EQUAL(data_set.size(), 1);
+ BOOST_REQUIRE(data_set.has("deadbeef"));
+ BOOST_REQUIRE(data_set.get_vr("deadbeef") == dcmtkpp::VR::FL);
+ BOOST_REQUIRE(data_set.is_real("deadbeef"));
+ BOOST_REQUIRE(data_set.as_real("deadbeef") == dcmtkpp::Value::Reals({1.2, 3.4}));
+}
+
+BOOST_AUTO_TEST_CASE(AsDataSetStrings)
+{
+ std::stringstream data;
+ data << "{ \"deadbeef\": { \"vr\": \"CS\", \"Value\": [\"FOO\", \"BAR\"] } }";
+ Json::Value json;
+ data >> json;
+
+ dcmtkpp::DataSet const data_set = dcmtkpp::as_dataset(json);
+ BOOST_REQUIRE_EQUAL(data_set.size(), 1);
+ BOOST_REQUIRE(data_set.has("deadbeef"));
+ BOOST_REQUIRE(data_set.get_vr("deadbeef") == dcmtkpp::VR::CS);
+ BOOST_REQUIRE(data_set.is_string("deadbeef"));
+ BOOST_REQUIRE(data_set.as_string("deadbeef") == dcmtkpp::Value::Strings({"FOO", "BAR"}));
+}
+
+BOOST_AUTO_TEST_CASE(AsDataSetPersonName)
+{
+ std::stringstream data;
+ data << "{ \"deadbeef\": { \"vr\": \"PN\", \"Value\": [ ";
+ data << "{ \"Alphabetic\": \"Alpha^Betic\" , ";
+ data << "\"Ideographic\": \"Ideo^Graphic\" , ";
+ data << "\"Phonetic\": \"Pho^Netic\" } ";
+ data << " ] } }";
+ Json::Value json;
+ data >> json;
+
+ dcmtkpp::DataSet const data_set = dcmtkpp::as_dataset(json);
+ BOOST_REQUIRE_EQUAL(data_set.size(), 1);
+ BOOST_REQUIRE(data_set.has("deadbeef"));
+ BOOST_REQUIRE(data_set.get_vr("deadbeef") == dcmtkpp::VR::PN);
+ BOOST_REQUIRE(data_set.is_string("deadbeef"));
+ BOOST_REQUIRE(data_set.as_string("deadbeef") == dcmtkpp::Value::Strings(
+ {"Alpha^Betic=Ideo^Graphic=Pho^Netic"}));
+}
+
+BOOST_AUTO_TEST_CASE(AsDataSetDataSets)
+{
+ std::stringstream data;
+ data << "{ \"deadbeef\": { \"vr\": \"SQ\", \"Value\": [ ";
+ data << "{ \"beeff00d\": { \"vr\": \"SS\", \"Value\": [1, 2] } }";
+ data << " ] } }";
+ Json::Value json;
+ data >> json;
+
+ dcmtkpp::DataSet const data_set = dcmtkpp::as_dataset(json);
+ BOOST_REQUIRE_EQUAL(data_set.size(), 1);
+ BOOST_REQUIRE(data_set.has("deadbeef"));
+ BOOST_REQUIRE(data_set.get_vr("deadbeef") == dcmtkpp::VR::SQ);
+ BOOST_REQUIRE(data_set.is_data_set("deadbeef"));
+
+ dcmtkpp::DataSet item;
+ item.add(0xbeeff00d,
+ dcmtkpp::Element(dcmtkpp::Value::Integers({1,2}), dcmtkpp::VR::SS));
+ BOOST_REQUIRE(data_set.as_data_set("deadbeef") == dcmtkpp::Value::DataSets({item}));
+}
+
+
+BOOST_AUTO_TEST_CASE(AsDataSetBinary)
+{
+ std::stringstream data;
+ data << "{ \"deadbeef\": { \"vr\": \"OB\", \"InlineBinary\": \"AQIDBAU=\" } }";
+ Json::Value json;
+ data >> json;
+
+ dcmtkpp::DataSet const data_set = dcmtkpp::as_dataset(json);
+ BOOST_REQUIRE_EQUAL(data_set.size(), 1);
+ BOOST_REQUIRE(data_set.has("deadbeef"));
+ BOOST_REQUIRE(data_set.get_vr("deadbeef") == dcmtkpp::VR::OB);
+ BOOST_REQUIRE(data_set.is_binary("deadbeef"));
+ BOOST_REQUIRE(data_set.as_binary("deadbeef") == dcmtkpp::Value::Binary(
+ {0x1, 0x2, 0x3, 0x4, 0x5}));
+}
diff --git a/tests/code/unicode.cpp b/tests/code/unicode.cpp
new file mode 100644
index 0000000..5d23016
--- /dev/null
+++ b/tests/code/unicode.cpp
@@ -0,0 +1,258 @@
+#define BOOST_TEST_MODULE unicode
+#include <boost/test/unit_test.hpp>
+
+#include <dcmtk/config/osconfig.h>
+#include <dcmtk/dcmdata/dctk.h>
+
+#include "dcmtkpp/conversion.h"
+#include "dcmtkpp/DataSet.h"
+#include "dcmtkpp/unicode.h"
+
+BOOST_AUTO_TEST_CASE(SCSARAB)
+{
+ dcmtkpp::Value::Strings const specific_character_set = { "ISO_IR 127" };
+ std::string const source =
+ "\xe2\xc8\xc7\xe6\xea" "^" "\xe4\xe6\xd2\xc7\xd1";
+ std::string const expected =
+ "\xd9\x82\xd8\xa8\xd8\xa7\xd9\x86\xd9\x8a"
+ "^"
+ "\xd9\x84\xd9\x86\xd8\xb2\xd8\xa7\xd8\xb1";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSFREN)
+{
+ dcmtkpp::Value::Strings const specific_character_set = { "ISO_IR 100" };
+ std::string const source = "Buc" "^" "J\xe9r\xf4me";
+ std::string const expected =
+ "Buc" "^" "J\xc3\xa9r\xc3\xb4me";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSGERM)
+{
+ dcmtkpp::Value::Strings const specific_character_set = { "ISO_IR 100" };
+ std::string const source =
+ "\xc4neas" "^" "R\xfc" "diger";
+ std::string const expected =
+ "\xc3\x84neas" "^" "R\xc3\xbc" "diger";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSGREEK)
+{
+ dcmtkpp::Value::Strings const specific_character_set = { "ISO_IR 126" };
+ std::string const source = "\xc4\xe9\xef\xed\xf5\xf3\xe9\xef\xf2";
+ std::string const expected =
+ "\xce\x94\xce\xb9\xce\xbf\xce\xbd\xcf\x85\xcf\x83\xce\xb9\xce\xbf\xcf\x82";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSH31)
+{
+ dcmtkpp::Value::Strings const specific_character_set =
+ { "", "ISO 2022 IR 87" };
+ std::string const source =
+ "Yamada" "^" "Tarou"
+ "="
+ "\x1b\x24\x42\x3b\x33\x45\x44\x1b\x28\x42"
+ "^" "\x1b\x24\x42\x42\x40\x4f\x3a\x1b\x28\x42"
+ "="
+ "\x1b\x24\x42\x24\x64\x24\x5e\x24\x40\x1b\x28\x42"
+ "^" "\x1b\x24\x42\x24\x3f\x24\x6d\x24\x26\x1b\x28\x42";
+ std::string const expected =
+ "Yamada" "^" "Tarou"
+ "="
+ "\xe5\xb1\xb1\xe7\x94\xb0" "^" "\xe5\xa4\xaa\xe9\x83\x8e"
+ "="
+ "\xe3\x82\x84\xe3\x81\xbe\xe3\x81\xa0"
+ "^" "\xe3\x81\x9f\xe3\x82\x8d\xe3\x81\x86";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSH32)
+{
+ dcmtkpp::Value::Strings const specific_character_set =
+ { "ISO 2022 IR 13", "ISO 2022 IR 87" };
+ std::string const source =
+ "\xd4\xcf\xc0\xde" "^" "\xc0\xdb\xb3"
+ "="
+ "\x1b\x24\x42\x3b\x33\x45\x44\x1b\x28\x4a"
+ "^" "\x1b\x24\x42\x42\x40\x4f\x3a\x1b\x28\x4a"
+ "="
+ "\x1b\x24\x42\x24\x64\x24\x5e\x24\x40\x1b\x28\x4a"
+ "\x5e\x1b\x24\x42\x24\x3f\x24\x6d\x24\x26\x1b\x28\x4a";
+ std::string const expected =
+ "\xef\xbe\x94\xef\xbe\x8f\xef\xbe\x80\xef\xbe\x9e"
+ "^" "\xef\xbe\x80\xef\xbe\x9b\xef\xbd\xb3"
+ "="
+ "\xe5\xb1\xb1\xe7\x94\xb0"
+ "^" "\xe5\xa4\xaa\xe9\x83\x8e"
+ "="
+ "\xe3\x82\x84\xe3\x81\xbe\xe3\x81\xa0"
+ "^" "\xe3\x81\x9f\xe3\x82\x8d\xe3\x81\x86";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSHBRW)
+{
+ dcmtkpp::Value::Strings const specific_character_set = { "ISO_IR 138" };
+ std::string const source = "\xf9\xf8\xe5\xef" "^" "\xe3\xe1\xe5\xf8\xe4";
+ std::string const expected =
+ "\xd7\xa9\xd7\xa8\xd7\x95\xd7\x9f"
+ "^" "\xd7\x93\xd7\x91\xd7\x95\xd7\xa8\xd7\x94";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSI2)
+{
+ dcmtkpp::Value::Strings const specific_character_set =
+ { "", "ISO 2022 IR 149" };
+
+ std::string const source =
+ "\x48\x6f\x6e\x67" "^" "\x47\x69\x6c\x64\x6f\x6e\x67"
+ "="
+ "\x1b\x24\x29\x43\xfb\xf3" "^" "\x1b\x24\x29\x43\xd1\xce\xd4\xd7"
+ "="
+ "\x1b\x24\x29\x43\xc8\xab" "^" "\x1b\x24\x29\x43\xb1\xe6\xb5\xbf";
+ std::string const expected =
+ "\x48\x6f\x6e\x67" "^" "\x47\x69\x6c\x64\x6f\x6e\x67"
+ "="
+ "\xe6\xb4\xaa" "^" "\xe5\x90\x89\xe6\xb4\x9e"
+ "="
+ "\xed\x99\x8d" "^" "\xea\xb8\xb8\xeb\x8f\x99";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSRUSS)
+{
+ dcmtkpp::Value::Strings const specific_character_set = { "ISO_IR 144" };
+ std::string const source = "\xbb\xee\xda\x63\x65\xdc\xd1\x79\x70\xd3";
+ std::string const expected =
+ "\xd0\x9b\xd1\x8e\xd0\xba\x63\x65\xd0\xbc\xd0\xb1\x79\x70\xd0\xb3";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSX1)
+{
+ dcmtkpp::Value::Strings const specific_character_set = { "ISO_IR 192" };
+ std::string const source =
+ "Wang" "^" "XiaoDong"
+ "="
+ "\xe7\x8e\x8b" "^" "\xe5\xb0\x8f\xe6\x9d\xb1"
+ "=";
+ std::string const expected =
+ "Wang" "^" "XiaoDong"
+ "\x3d\xe7\x8e\x8b" "^" "\xe5\xb0\x8f\xe6\x9d\xb1"
+ "=";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+BOOST_AUTO_TEST_CASE(SCSX2)
+{
+ dcmtkpp::Value::Strings const specific_character_set = { "GB18030" };
+ std::string const source =
+ "Wang" "^" "XiaoDong"
+ "=" ""
+ "\xcd\xf5" "^" "\xd0\xa1\xb6\xab"
+ "=";
+ std::string const expected =
+ "Wang" "^" "XiaoDong"
+ "="
+ "\xe7\x8e\x8b" "^" "\xe5\xb0\x8f\xe4\xb8\x9c"
+ "=";
+
+ std::string const utf8 = dcmtkpp::as_utf8(
+ source, specific_character_set, true);
+ BOOST_REQUIRE_EQUAL(utf8, expected);
+}
+
+/*
+dcmtkpp::DataSet read(std::string const & filename)
+{
+ DcmFileFormat format;
+
+ OFCondition const condition = format.loadFile(filename.c_str());
+ if(condition.bad())
+ {
+ throw dcmtkpp::Exception(condition);
+ }
+
+ dcmtkpp::DataSet const result = dcmtkpp::convert(format.getDataset());
+
+ return result;
+}
+
+
+int main(int argc, char ** argv)
+{
+ for(char** argument=argv+1; argument != argv+argc; ++argument)
+ {
+ std::cout << "Reading " << *argument << std::endl;
+
+ dcmtkpp::DataSet data_set;
+ try
+ {
+ data_set = read(*argument);
+ }
+ catch(dcmtkpp::Exception const & e)
+ {
+ std::cerr << "Could not read " << *argument << ": " << e.what() << "\n";
+ continue;
+ }
+
+ std::string patient_name;
+ try
+ {
+ patient_name = dcmtkpp::as_utf8(
+ data_set.as_string("PatientName")[0],
+ data_set.as_string("SpecificCharacterSet"), true);
+ }
+ catch(dcmtkpp::Exception const & e)
+ {
+ std::cerr << "Could not convert PatientName to UTF-8: " << e.what() << "\n";
+ continue;
+ }
+
+ std::cout << " dcmtkpp::Value::Strings const specific_character_set = {\n";
+ for(auto const & c: data_set.as_string("SpecificCharacterSet"))
+ {
+ std::cout << " " << "\"" << c << "\",\n";
+ }
+ std::cout << " };\n";
+ std::cout << "Patient Name: \"" << patient_name << "\"\n";
+ }
+
+ return 0;
+}
+*/
diff --git a/tests/run.sh b/tests/run.sh
new file mode 100755
index 0000000..fa8a490
--- /dev/null
+++ b/tests/run.sh
@@ -0,0 +1,57 @@
+#! /bin/sh
+
+set -e
+set -u
+
+configure() {
+ cat > ${directory}/config << EOF
+HostTable BEGIN
+remote = (REMOTE, localhost, 11112)
+local = (LOCAL, localhost, 11113)
+HostTable END
+
+AETable BEGIN
+REMOTE ${directory} RW (10, 1024mb) local
+AETable END
+EOF
+}
+
+add_data() {
+dump2dcm --write-xfer-little /dev/stdin ${directory}/data.dcm <<EOF
+(0008,0016) UI =RawDataStorage
+(0008,0018) UI [2.25.95090344942250266709587559073467305647]
+(0010,0010) PN [Doe^John]
+(0010,0020) LO [DJ001]
+EOF
+storescu -aet LOCAL -aec REMOTE localhost 11112 ${directory}/data.dcm
+}
+
+start_scp() {
+ dcmqrscp -c ${directory}/config 11112 &
+ PID=$!
+ sleep 1
+}
+
+stop_scp() {
+ kill ${PID}
+}
+
+clean() {
+ rm -rf ${directory}
+}
+
+directory=$(mktemp -d dcmtkpp.XXX)
+configure
+start_scp
+add_data
+
+export DCMTKPP_OWN_AET=LOCAL
+export DCMTKPP_PEER_HOST_NAME=localhost
+export DCMTKPP_PEER_PORT=11112
+export DCMTKPP_PEER_AET=REMOTE
+
+ctest --no-compress-output -T Test || true
+
+stop_scp
+clean
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/dcmtkpp.git
More information about the debian-med-commit
mailing list