Digital Imaging and Communications in Medicine (DICOM) file format: GraphViz block diagram (.dot) source

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.

File extension

dcm

KS implementation details

License: MIT

References

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.

GraphViz block diagram source

dicom.dot

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 == &quot;OB&quot;) || (vr == &quot;OD&quot;) || (vr == &quot;OF&quot;) || (vr == &quot;OL&quot;) || (vr == &quot;OW&quot;) || (vr == &quot;SQ&quot;) || (vr == &quot;UC&quot;) || (vr == &quot;UR&quot;) || (vr == &quot;UT&quot;) || (vr == &quot;UN&quot;)) </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 &lt;&lt; 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 &lt;&lt; 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) &amp;&amp; ( ((vr == &quot;OB&quot;) || (vr == &quot;OD&quot;) || (vr == &quot;OF&quot;) || (vr == &quot;OL&quot;) || (vr == &quot;OW&quot;) || (vr == &quot;SQ&quot;) || (vr == &quot;UC&quot;) || (vr == &quot;UR&quot;) || (vr == &quot;UT&quot;) || (vr == &quot;UN&quot;)) )) </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) &amp;&amp; (_.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"];
}