Exchangeable image file format (Exif): Graphviz block diagram (.dot) source

This page hosts a formal specification of Exchangeable image file format (Exif) using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Graphviz block diagram source

exif.dot

digraph {
	rankdir=LR;
	node [shape=plaintext];
	subgraph cluster__exif {
		label="Exif";
		graph[style=dotted];

		exif__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="endianness_pos">0</TD><TD PORT="endianness_size">2</TD><TD>u2le</TD><TD PORT="endianness_type">endianness</TD></TR>
			<TR><TD PORT="body_pos">2</TD><TD PORT="body_size">6</TD><TD>ExifBody</TD><TD PORT="body_type">body</TD></TR>
		</TABLE>>];
		subgraph cluster__exif_body {
			label="Exif::ExifBody";
			graph[style=dotted];

			exif_body__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="magic_pos">0</TD><TD PORT="magic_size">2</TD><TD>u2</TD><TD PORT="magic_type">magic</TD></TR>
				<TR><TD COLSPAN="4" PORT="magic__valid">must be equal to 42</TD></TR>
				<TR><TD PORT="ofs_ifd0_pos">2</TD><TD PORT="ofs_ifd0_size">4</TD><TD>u4</TD><TD PORT="ofs_ifd0_type">ofs_ifd0</TD></TR>
			</TABLE>>];
			exif_body__inst__ifd0 [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="ifd0_pos">ofs_ifd0</TD><TD PORT="ifd0_size">...</TD><TD>Ifd</TD><TD PORT="ifd0_type">ifd0</TD></TR>
			</TABLE>>];
			subgraph cluster__ascii_string {
				label="Exif::ExifBody::AsciiString";
				graph[style=dotted];

				ascii_string__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="value_pos">0</TD><TD PORT="value_size">...</TD><TD>term=0, ignore EOS</TD><TD PORT="value_type">value</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__doubles {
				label="Exif::ExifBody::Doubles";
				graph[style=dotted];

				doubles__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="values_pos">0</TD><TD PORT="values_size">8</TD><TD>f8</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__floats {
				label="Exif::ExifBody::Floats";
				graph[style=dotted];

				floats__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="values_pos">0</TD><TD PORT="values_size">4</TD><TD>f4</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__ifd {
				label="Exif::ExifBody::Ifd";
				graph[style=dotted];

				ifd__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="num_fields_pos">0</TD><TD PORT="num_fields_size">2</TD><TD>u2</TD><TD PORT="num_fields_type">num_fields</TD></TR>
					<TR><TD PORT="fields_pos">2</TD><TD PORT="fields_size">12</TD><TD>IfdField</TD><TD PORT="fields_type">fields</TD></TR>
					<TR><TD COLSPAN="4" PORT="fields__repeat">repeat num_fields times</TD></TR>
					<TR><TD PORT="ofs_next_ifd_pos">...</TD><TD PORT="ofs_next_ifd_size">4</TD><TD>u4</TD><TD PORT="ofs_next_ifd_type">ofs_next_ifd</TD></TR>
				</TABLE>>];
				ifd__inst__next_ifd [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="next_ifd_pos">ofs_next_ifd</TD><TD PORT="next_ifd_size">...</TD><TD>Ifd</TD><TD PORT="next_ifd_type">next_ifd</TD></TR>
					<TR><TD COLSPAN="4" PORT="next_ifd__if">if ofs_next_ifd != 0</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__ifd_field {
				label="Exif::ExifBody::IfdField";
				graph[style=dotted];

				ifd_field__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_raw_pos">0</TD><TD PORT="tag_raw_size">2</TD><TD>u2</TD><TD PORT="tag_raw_type">tag_raw</TD></TR>
					<TR><TD PORT="field_type_pos">2</TD><TD PORT="field_type_size">2</TD><TD>u2→FieldType</TD><TD PORT="field_type_type">field_type</TD></TR>
					<TR><TD PORT="num_values_pos">4</TD><TD PORT="num_values_size">4</TD><TD>u4</TD><TD PORT="num_values_type">num_values</TD></TR>
					<TR><TD PORT="ofs_data_pos">8</TD><TD PORT="ofs_data_size">4</TD><TD>u4</TD><TD PORT="ofs_data_type">ofs_data</TD></TR>
					<TR><TD COLSPAN="4" PORT="ofs_data__if">if !(has_immediate_data)</TD></TR>
				</TABLE>>];
				ifd_field__inst__bytes_per_value [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
					<TR><TD>bytes_per_value</TD><TD>( ((field_type == :field_type_byte) || (field_type == :field_type_ascii) || (field_type == :field_type_sbyte) || (field_type == :field_type_undefined) || (field_type == :field_type_utf8))  ? 1 : ( ((field_type == :field_type_short) || (field_type == :field_type_sshort))  ? 2 : ( ((field_type == :field_type_long) || (field_type == :field_type_slong) || (field_type == :field_type_float) || (field_type == :field_type_ifd))  ? 4 : ( ((field_type == :field_type_rational) || (field_type == :field_type_srational) || (field_type == :field_type_double))  ? 8 : 0))))</TD></TR>
				</TABLE>>];
				ifd_field__inst__data [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="data_pos">(has_immediate_data ? 8 : ofs_data)</TD><TD PORT="data_size">...</TD><TD>switch (field_type)</TD><TD PORT="data_type">data</TD></TR>
				</TABLE>>];
				ifd_field__inst__gps_tag [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
					<TR><TD>gps_tag</TD><TD>Kaitai::Struct::Stream::resolve_enum(Exif::GPS_TAG, tag_raw)</TD></TR>
				</TABLE>>];
				ifd_field__inst__has_immediate_data [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
					<TR><TD>has_immediate_data</TD><TD>len_data &lt;= 4</TD></TR>
				</TABLE>>];
				ifd_field__inst__len_data [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
					<TR><TD>len_data</TD><TD>bytes_per_value * num_values</TD></TR>
				</TABLE>>];
				ifd_field__inst__sub_ifd [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="sub_ifd_pos">(field_type == :field_type_slong ? data.values.first : data.values.first)</TD><TD PORT="sub_ifd_size">...</TD><TD>Ifd</TD><TD PORT="sub_ifd_type">sub_ifd</TD></TR>
					<TR><TD COLSPAN="4" PORT="sub_ifd__if">if  ((num_values == 1) &amp;&amp; ( ((field_type == :field_type_long) || (field_type == :field_type_ifd) || ( ((field_type == :field_type_slong) &amp;&amp; (data.values.first &gt;= 0)) )) ) &amp;&amp; ( ((tag == :tag_exif_offset) || (tag == :tag_interop_offset) || (tag == :tag_gps_info)) )) </TD></TR>
				</TABLE>>];
				ifd_field__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(Exif::TAG, tag_raw)</TD></TR>
				</TABLE>>];
ifd_field__inst__data_data_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
	<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
	<TR><TD>:field_type_ascii</TD><TD PORT="case0">AsciiString</TD></TR>
	<TR><TD>:field_type_double</TD><TD PORT="case1">Doubles</TD></TR>
	<TR><TD>:field_type_float</TD><TD PORT="case2">Floats</TD></TR>
	<TR><TD>:field_type_ifd</TD><TD PORT="case3">Longs</TD></TR>
	<TR><TD>:field_type_long</TD><TD PORT="case4">Longs</TD></TR>
	<TR><TD>:field_type_rational</TD><TD PORT="case5">Rationals</TD></TR>
	<TR><TD>:field_type_sbyte</TD><TD PORT="case6">Sbytes</TD></TR>
	<TR><TD>:field_type_short</TD><TD PORT="case7">Shorts</TD></TR>
	<TR><TD>:field_type_slong</TD><TD PORT="case8">Slongs</TD></TR>
	<TR><TD>:field_type_srational</TD><TD PORT="case9">Srationals</TD></TR>
	<TR><TD>:field_type_sshort</TD><TD PORT="case10">Sshorts</TD></TR>
	<TR><TD>:field_type_utf8</TD><TD PORT="case11">Utf8String</TD></TR>
</TABLE>>];
			}
			subgraph cluster__longs {
				label="Exif::ExifBody::Longs";
				graph[style=dotted];

				longs__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="values_pos">0</TD><TD PORT="values_size">4</TD><TD>u4</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__rational {
				label="Exif::ExifBody::Rational";
				graph[style=dotted];

				rational__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="value_num_pos">0</TD><TD PORT="value_num_size">4</TD><TD>u4</TD><TD PORT="value_num_type">value_num</TD></TR>
					<TR><TD PORT="value_den_pos">4</TD><TD PORT="value_den_size">4</TD><TD>u4</TD><TD PORT="value_den_type">value_den</TD></TR>
				</TABLE>>];
				rational__inst__value [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
					<TR><TD>value</TD><TD>(value_num + 0.0) / value_den</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__rationals {
				label="Exif::ExifBody::Rationals";
				graph[style=dotted];

				rationals__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="values_pos">0</TD><TD PORT="values_size">8</TD><TD>Rational</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__sbytes {
				label="Exif::ExifBody::Sbytes";
				graph[style=dotted];

				sbytes__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="values_pos">0</TD><TD PORT="values_size">1</TD><TD>s1</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__shorts {
				label="Exif::ExifBody::Shorts";
				graph[style=dotted];

				shorts__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="values_pos">0</TD><TD PORT="values_size">2</TD><TD>u2</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__slongs {
				label="Exif::ExifBody::Slongs";
				graph[style=dotted];

				slongs__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="values_pos">0</TD><TD PORT="values_size">4</TD><TD>s4</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__srational {
				label="Exif::ExifBody::Srational";
				graph[style=dotted];

				srational__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="value_num_pos">0</TD><TD PORT="value_num_size">4</TD><TD>s4</TD><TD PORT="value_num_type">value_num</TD></TR>
					<TR><TD PORT="value_den_pos">4</TD><TD PORT="value_den_size">4</TD><TD>s4</TD><TD PORT="value_den_type">value_den</TD></TR>
				</TABLE>>];
				srational__inst__value [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
					<TR><TD>value</TD><TD>(value_num + 0.0) / value_den</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__srationals {
				label="Exif::ExifBody::Srationals";
				graph[style=dotted];

				srationals__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="values_pos">0</TD><TD PORT="values_size">8</TD><TD>Srational</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__sshorts {
				label="Exif::ExifBody::Sshorts";
				graph[style=dotted];

				sshorts__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="values_pos">0</TD><TD PORT="values_size">2</TD><TD>s2</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat _parent.num_values times</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__utf8_string {
				label="Exif::ExifBody::Utf8String";
				graph[style=dotted];

				utf8_string__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="value_pos">0</TD><TD PORT="value_size">...</TD><TD>str(term=0, ignore EOS, UTF-8)</TD><TD PORT="value_type">value</TD></TR>
				</TABLE>>];
			}
		}
	}
	exif__seq:body_type -> exif_body__seq [style=bold];
	exif_body__seq:ofs_ifd0_type -> exif_body__inst__ifd0:ifd0_pos [color="#404040"];
	exif_body__inst__ifd0:ifd0_type -> ifd__seq [style=bold];
	ifd_field__seq:num_values_type -> doubles__seq:values__repeat [color="#404040"];
	ifd_field__seq:num_values_type -> floats__seq:values__repeat [color="#404040"];
	ifd__seq:fields_type -> ifd_field__seq [style=bold];
	ifd__seq:num_fields_type -> ifd__seq:fields__repeat [color="#404040"];
	ifd__seq:ofs_next_ifd_type -> ifd__inst__next_ifd:next_ifd_pos [color="#404040"];
	ifd__inst__next_ifd:next_ifd_type -> ifd__seq [style=bold];
	ifd__seq:ofs_next_ifd_type -> ifd__inst__next_ifd:next_ifd__if [color="#404040"];
	ifd_field__inst__has_immediate_data:has_immediate_data_type -> ifd_field__seq:ofs_data__if [color="#404040"];
	ifd_field__seq:field_type_type -> ifd_field__inst__bytes_per_value [color="#404040"];
	ifd_field__inst__has_immediate_data:has_immediate_data_type -> ifd_field__inst__data:data_pos [color="#404040"];
	ifd_field__seq:ofs_data_type -> ifd_field__inst__data:data_pos [color="#404040"];
	ifd_field__inst__data:data_type -> ifd_field__inst__data_data_switch [style=bold];
	ifd_field__inst__data_data_switch:case0 -> ascii_string__seq [style=bold];
	ifd_field__inst__data_data_switch:case1 -> doubles__seq [style=bold];
	ifd_field__inst__data_data_switch:case2 -> floats__seq [style=bold];
	ifd_field__inst__data_data_switch:case3 -> longs__seq [style=bold];
	ifd_field__inst__data_data_switch:case4 -> longs__seq [style=bold];
	ifd_field__inst__data_data_switch:case5 -> rationals__seq [style=bold];
	ifd_field__inst__data_data_switch:case6 -> sbytes__seq [style=bold];
	ifd_field__inst__data_data_switch:case7 -> shorts__seq [style=bold];
	ifd_field__inst__data_data_switch:case8 -> slongs__seq [style=bold];
	ifd_field__inst__data_data_switch:case9 -> srationals__seq [style=bold];
	ifd_field__inst__data_data_switch:case10 -> sshorts__seq [style=bold];
	ifd_field__inst__data_data_switch:case11 -> utf8_string__seq [style=bold];
	ifd_field__seq:field_type_type -> ifd_field__inst__data:data_type [color="#404040"];
	ifd_field__seq:tag_raw_type -> ifd_field__inst__gps_tag [color="#404040"];
	ifd_field__inst__len_data:len_data_type -> ifd_field__inst__has_immediate_data [color="#404040"];
	ifd_field__inst__bytes_per_value:bytes_per_value_type -> ifd_field__inst__len_data [color="#404040"];
	ifd_field__seq:num_values_type -> ifd_field__inst__len_data [color="#404040"];
	ifd_field__seq:field_type_type -> ifd_field__inst__sub_ifd:sub_ifd_pos [color="#404040"];
	slongs__seq:values_type -> ifd_field__inst__sub_ifd:sub_ifd_pos [color="#404040"];
	longs__seq:values_type -> ifd_field__inst__sub_ifd:sub_ifd_pos [color="#404040"];
	ifd_field__inst__sub_ifd:sub_ifd_type -> ifd__seq [style=bold];
	ifd_field__seq:num_values_type -> ifd_field__inst__sub_ifd:sub_ifd__if [color="#404040"];
	ifd_field__seq:field_type_type -> ifd_field__inst__sub_ifd:sub_ifd__if [color="#404040"];
	slongs__seq:values_type -> ifd_field__inst__sub_ifd:sub_ifd__if [color="#404040"];
	ifd_field__inst__tag:tag_type -> ifd_field__inst__sub_ifd:sub_ifd__if [color="#404040"];
	ifd_field__seq:tag_raw_type -> ifd_field__inst__tag [color="#404040"];
	ifd_field__seq:num_values_type -> longs__seq:values__repeat [color="#404040"];
	rational__seq:value_num_type -> rational__inst__value [color="#404040"];
	rational__seq:value_den_type -> rational__inst__value [color="#404040"];
	rationals__seq:values_type -> rational__seq [style=bold];
	ifd_field__seq:num_values_type -> rationals__seq:values__repeat [color="#404040"];
	ifd_field__seq:num_values_type -> sbytes__seq:values__repeat [color="#404040"];
	ifd_field__seq:num_values_type -> shorts__seq:values__repeat [color="#404040"];
	ifd_field__seq:num_values_type -> slongs__seq:values__repeat [color="#404040"];
	srational__seq:value_num_type -> srational__inst__value [color="#404040"];
	srational__seq:value_den_type -> srational__inst__value [color="#404040"];
	srationals__seq:values_type -> srational__seq [style=bold];
	ifd_field__seq:num_values_type -> srationals__seq:values__repeat [color="#404040"];
	ifd_field__seq:num_values_type -> sshorts__seq:values__repeat [color="#404040"];
}