DICOM (Digital Imaging and Communications in Medicine), AKA NEMA PS3, AKA ISO 12052:2006, is a file format and network protocol standard for medical imaging purposes. This parser covers file format, typically written by various medical equipment, such as radiography, computer tomography scans, MRT, ultrasonography, etc.
DICOM defines two transfer syntaxes: implicit and explicit. This
top-level parser attempts to autodetect and handle both of them. If
any problems arise, one can use file_explicit
and file_implicit
subtypes to force parsing in particular transfer syntax.
This page hosts a formal specification of Digital Imaging and Communications in Medicine (DICOM) file format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
digraph {
rankdir=LR;
node [shape=plaintext];
subgraph cluster__dicom {
label="Dicom";
graph[style=dotted];
dicom__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
<TR><TD PORT="file_header_pos">0</TD><TD PORT="file_header_size">132</TD><TD>TFileHeader</TD><TD PORT="file_header_type">file_header</TD></TR>
<TR><TD PORT="elements_pos">132</TD><TD PORT="elements_size">...</TD><TD>TDataElementImplicit</TD><TD PORT="elements_type">elements</TD></TR>
<TR><TD COLSPAN="4" PORT="elements__repeat">repeat to end of stream</TD></TR>
</TABLE>>];
subgraph cluster__t_file_header {
label="Dicom::TFileHeader";
graph[style=dotted];
t_file_header__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
<TR><TD PORT="preamble_pos">0</TD><TD PORT="preamble_size">128</TD><TD></TD><TD PORT="preamble_type">preamble</TD></TR>
<TR><TD PORT="magic_pos">128</TD><TD PORT="magic_size">4</TD><TD></TD><TD PORT="magic_type">magic</TD></TR>
</TABLE>>];
}
subgraph cluster__t_data_element_explicit {
label="Dicom::TDataElementExplicit";
graph[style=dotted];
t_data_element_explicit__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
<TR><TD PORT="tag_group_pos">0</TD><TD PORT="tag_group_size">2</TD><TD>u2le</TD><TD PORT="tag_group_type">tag_group</TD></TR>
<TR><TD PORT="tag_elem_pos">2</TD><TD PORT="tag_elem_size">2</TD><TD>u2le</TD><TD PORT="tag_elem_type">tag_elem</TD></TR>
<TR><TD PORT="vr_pos">4</TD><TD PORT="vr_size">2</TD><TD>str(ASCII)</TD><TD PORT="vr_type">vr</TD></TR>
<TR><TD PORT="reserved_pos">6</TD><TD PORT="reserved_size">2</TD><TD>u2le</TD><TD PORT="reserved_type">reserved</TD></TR>
<TR><TD PORT="value_len_pos">8</TD><TD PORT="value_len_size">...</TD><TD>switch (is_long_len)</TD><TD PORT="value_len_type">value_len</TD></TR>
<TR><TD PORT="value_pos">...</TD><TD PORT="value_size">value_len</TD><TD></TD><TD PORT="value_type">value</TD></TR>
<TR><TD PORT="items_pos">...</TD><TD PORT="items_size">...</TD><TD>SeqItem</TD><TD PORT="items_type">items</TD></TR>
<TR><TD COLSPAN="4" PORT="items__repeat">repeat until _.tag_elem == 57565</TD></TR>
<TR><TD PORT="elements_implicit_pos">...</TD><TD PORT="elements_implicit_size">...</TD><TD>TDataElementImplicit</TD><TD PORT="elements_implicit_type">elements_implicit</TD></TR>
<TR><TD COLSPAN="4" PORT="elements_implicit__repeat">repeat to end of stream</TD></TR>
</TABLE>>];
t_data_element_explicit__inst__is_forced_implicit [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>is_forced_implicit</TD><TD>tag_group == 65534</TD></TR>
</TABLE>>];
t_data_element_explicit__inst__is_long_len [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>is_long_len</TD><TD> ((is_forced_implicit) || (vr == "OB") || (vr == "OD") || (vr == "OF") || (vr == "OL") || (vr == "OW") || (vr == "SQ") || (vr == "UC") || (vr == "UR") || (vr == "UT") || (vr == "UN")) </TD></TR>
</TABLE>>];
t_data_element_explicit__inst__is_transfer_syntax_change_implicit [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>is_transfer_syntax_change_implicit</TD><TD>false</TD></TR>
</TABLE>>];
t_data_element_explicit__inst__tag [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>tag</TD><TD>Kaitai::Struct::Stream::resolve_enum(Dicom::TAGS, ((tag_group << 16) | tag_elem))</TD></TR>
</TABLE>>];
t_data_element_explicit__seq_value_len_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
</TABLE>>];
}
subgraph cluster__t_data_element_implicit {
label="Dicom::TDataElementImplicit";
graph[style=dotted];
t_data_element_implicit__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
<TR><TD PORT="tag_group_pos">0</TD><TD PORT="tag_group_size">2</TD><TD>u2le</TD><TD PORT="tag_group_type">tag_group</TD></TR>
<TR><TD PORT="tag_elem_pos">2</TD><TD PORT="tag_elem_size">2</TD><TD>u2le</TD><TD PORT="tag_elem_type">tag_elem</TD></TR>
<TR><TD PORT="vr_pos">4</TD><TD PORT="vr_size">2</TD><TD>str(ASCII)</TD><TD PORT="vr_type">vr</TD></TR>
<TR><TD PORT="reserved_pos">6</TD><TD PORT="reserved_size">2</TD><TD>u2le</TD><TD PORT="reserved_type">reserved</TD></TR>
<TR><TD PORT="value_len_pos">8</TD><TD PORT="value_len_size">...</TD><TD>switch ((is_forced_explicit ? is_long_len : true))</TD><TD PORT="value_len_type">value_len</TD></TR>
<TR><TD PORT="value_pos">...</TD><TD PORT="value_size">value_len</TD><TD></TD><TD PORT="value_type">value</TD></TR>
<TR><TD PORT="items_pos">...</TD><TD PORT="items_size">...</TD><TD>SeqItem</TD><TD PORT="items_type">items</TD></TR>
<TR><TD COLSPAN="4" PORT="items__repeat">repeat until _.tag_elem == 57565</TD></TR>
<TR><TD PORT="elements_pos">...</TD><TD PORT="elements_size">...</TD><TD>TDataElementExplicit</TD><TD PORT="elements_type">elements</TD></TR>
<TR><TD COLSPAN="4" PORT="elements__repeat">repeat to end of stream</TD></TR>
</TABLE>>];
t_data_element_implicit__inst__tag [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>tag</TD><TD>Kaitai::Struct::Stream::resolve_enum(Dicom::TAGS, ((tag_group << 16) | tag_elem))</TD></TR>
</TABLE>>];
t_data_element_implicit__inst__is_transfer_syntax_change_explicit [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>is_transfer_syntax_change_explicit</TD><TD>p_is_transfer_syntax_change_explicit</TD></TR>
</TABLE>>];
t_data_element_implicit__inst__is_long_len [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>is_long_len</TD><TD> ((is_forced_explicit) && ( ((vr == "OB") || (vr == "OD") || (vr == "OF") || (vr == "OL") || (vr == "OW") || (vr == "SQ") || (vr == "UC") || (vr == "UR") || (vr == "UT") || (vr == "UN")) )) </TD></TR>
</TABLE>>];
t_data_element_implicit__inst__p_is_transfer_syntax_change_explicit [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>p_is_transfer_syntax_change_explicit</TD><TD>value == [49, 46, 50, 46, 56, 52, 48, 46, 49, 48, 48, 48, 56, 46, 49, 46, 50, 46, 49, 0].pack('C*')</TD></TR>
</TABLE>>];
t_data_element_implicit__inst__is_forced_explicit [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
<TR><TD>is_forced_explicit</TD><TD>tag_group == 2</TD></TR>
</TABLE>>];
t_data_element_implicit__seq_value_len_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
</TABLE>>];
}
subgraph cluster__seq_item {
label="Dicom::SeqItem";
graph[style=dotted];
seq_item__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
<TR><TD PORT="tag_group_pos">0</TD><TD PORT="tag_group_size">2</TD><TD></TD><TD PORT="tag_group_type">tag_group</TD></TR>
<TR><TD PORT="tag_elem_pos">2</TD><TD PORT="tag_elem_size">2</TD><TD>u2le</TD><TD PORT="tag_elem_type">tag_elem</TD></TR>
<TR><TD PORT="value_len_pos">4</TD><TD PORT="value_len_size">4</TD><TD>u4le</TD><TD PORT="value_len_type">value_len</TD></TR>
<TR><TD PORT="value_pos">8</TD><TD PORT="value_size">value_len</TD><TD></TD><TD PORT="value_type">value</TD></TR>
<TR><TD PORT="items_pos">...</TD><TD PORT="items_size">...</TD><TD>TDataElementExplicit</TD><TD PORT="items_type">items</TD></TR>
<TR><TD COLSPAN="4" PORT="items__repeat">repeat until ((_.tag_group == 65534) && (_.tag_elem == 57357)) </TD></TR>
</TABLE>>];
}
}
dicom__seq:file_header_type -> t_file_header__seq [style=bold];
dicom__seq:elements_type -> t_data_element_implicit__seq [style=bold];
t_data_element_explicit__seq:value_len_type -> t_data_element_explicit__seq_value_len_switch [style=bold];
t_data_element_explicit__inst__is_long_len:is_long_len_type -> t_data_element_explicit__seq:value_len_type [color="#404040"];
t_data_element_explicit__seq:value_len_type -> t_data_element_explicit__seq:value_size [color="#404040"];
t_data_element_explicit__seq:items_type -> seq_item__seq [style=bold];
seq_item__seq:tag_elem_type -> t_data_element_explicit__seq:items__repeat [color="#404040"];
t_data_element_explicit__seq:elements_implicit_type -> t_data_element_implicit__seq [style=bold];
t_data_element_explicit__seq:tag_group_type -> t_data_element_explicit__inst__is_forced_implicit [color="#404040"];
t_data_element_explicit__inst__is_forced_implicit:is_forced_implicit_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:vr_type -> t_data_element_explicit__inst__is_long_len [color="#404040"];
t_data_element_explicit__seq:tag_group_type -> t_data_element_explicit__inst__tag [color="#404040"];
t_data_element_explicit__seq:tag_elem_type -> t_data_element_explicit__inst__tag [color="#404040"];
t_data_element_implicit__seq:value_len_type -> t_data_element_implicit__seq_value_len_switch [style=bold];
t_data_element_implicit__inst__is_forced_explicit:is_forced_explicit_type -> t_data_element_implicit__seq:value_len_type [color="#404040"];
t_data_element_implicit__inst__is_long_len:is_long_len_type -> t_data_element_implicit__seq:value_len_type [color="#404040"];
t_data_element_implicit__seq:value_len_type -> t_data_element_implicit__seq:value_size [color="#404040"];
t_data_element_implicit__seq:items_type -> seq_item__seq [style=bold];
seq_item__seq:tag_elem_type -> t_data_element_implicit__seq:items__repeat [color="#404040"];
t_data_element_implicit__seq:elements_type -> t_data_element_explicit__seq [style=bold];
t_data_element_implicit__seq:tag_group_type -> t_data_element_implicit__inst__tag [color="#404040"];
t_data_element_implicit__seq:tag_elem_type -> t_data_element_implicit__inst__tag [color="#404040"];
t_data_element_implicit__inst__p_is_transfer_syntax_change_explicit:p_is_transfer_syntax_change_explicit_type -> t_data_element_implicit__inst__is_transfer_syntax_change_explicit [color="#404040"];
t_data_element_implicit__inst__is_forced_explicit:is_forced_explicit_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:vr_type -> t_data_element_implicit__inst__is_long_len [color="#404040"];
t_data_element_implicit__seq:value_type -> t_data_element_implicit__inst__p_is_transfer_syntax_change_explicit [color="#404040"];
t_data_element_implicit__seq:tag_group_type -> t_data_element_implicit__inst__is_forced_explicit [color="#404040"];
seq_item__seq:value_len_type -> seq_item__seq:value_size [color="#404040"];
seq_item__seq:items_type -> t_data_element_explicit__seq [style=bold];
t_data_element_explicit__seq:tag_group_type -> seq_item__seq:items__repeat [color="#404040"];
t_data_element_explicit__seq:tag_elem_type -> seq_item__seq:items__repeat [color="#404040"];
}