ANSI INCITS 378-2004 Summary
This is a complete description of fingerprint template format defined in ANSI INCITS 378-2004 spec (often abbreviated as ANSI 378-2004 or even ambiguously as ANSI 378) except for the following changes:
- All content is distributed under permissive CC BY 4.0 license.
- Normative content was completely rewritten from scratch to avoid infringing copyrights.
- Non-normative commentary was dropped. Author added his own non-normative comments.
- Special notes were added for opensource and in-house software developers.
- Differences from other formats and other versions of this format were documented.
This format summary is complete in the sense that implementations written according to this document are also fully conforming implementations of ANSI INCITS 378-2004. There is no guarantee though and you should consult the original ANSI INCITS 378-2004 spec if in doubt.
This document was written by Robert Važan as part of his work on SourceAFIS fingerprint matcher using his legally obtained copy of ANSI INCITS 378-2004. Author has no affiliation with ANSI. This format summary is distributed free of charge under Creative Commons Attribution 4.0 International License to enable truly open implementation of the format in opensource software. Nevertheless, author discourages use of ANSI 378 and other so-called "standard" templates in favor of plain fingerprint images.
Human fingerprint recognition is usually performed in two separate steps: feature extraction and matching. Feature extraction takes fingerprint image (also called fingerprint sample), usually obtained from fingerprint reader (or fingerprint sensor) hardware, and produces so-called fingerprint template filled with fingerprint features useful for matching. Matching takes two fingerprint templates on input, compares fingerprint features contained in them, and produces similarity score on output, which is then compared to a threshold to produce match or non-match decision. There are many kinds of fingerprint features: minutiae (especially ridge endings and bifurcations), core and delta points, ridge shapes or patterns, orientation and ridge frequency fields, edges between minutiae, and many others.
Most fingerprint recognition systems have their own native fingerprint template format. Some people however insist on exchange of fingerprint templates between fingerprint recognition systems even though it is almost always a bad idea. ANSI 378-2004 is one of several fingerprint template formats that can be used for this purpose.
ANSI 378-2004 mainly encodes minutiae, including their position, angle, and type (ending, bifurcation, or other). It can optionally encode ridge counts on edges between minutiae and information about cores and deltas. It carries some fingerprint metadata, notably finger position (thumb, index, ...). It permits encoding several fingerprints in a single template.
This template format has a new version: ANSI 378-2009. The two versions can be differentiated by looking at the VERSION field, which is " 20\0" in this version and "030\0" in the 2009 version.
This format shares MAGIC and VERSION fields with ISO 19794-2:2005. The only way to differentiate the two formats is to look at the TOTALBYTES field.
When embedded in CBEFF (Common Biometric Exchange Framework Format, NISTIR 6529-A-2003) Biometric Data Block (BDB), this template format will have CBEFF Format Owner 0x1B (decimal 27), which is registered to INCITS Technical Committee M1. CBEFF Format Type registered for ANSI 378 is 0x201 when there are no extension blocks and 0x202 when extension blocks are present, including predefined extension blocks for ridge counts and cores/deltas.
The template is a binary file consisting of simple fields arranged into field groups. Fields or field groups may repeat. There are no keys or tags and fields are identified only by their position in the template. Numbers are in big-endian byte order.
There are two predefined extensions blocks. When EXTTYPE is 1, EXTDATA contains ridge count extension.
When EXTTYPE is 2, EXTDATA contains core and delta extension.
Fields and field groups
Template header (HEADER)
Header contains information common to all fingerprints in the template:
- template format identification: MAGIC, VERSION, TOTALBYTES, VENDOR, SUBFORMAT,
- sensor information: DEVID, DEVSTAMP, WIDTH, HEIGHT, RESOLUTIONX, RESOLUTIONY, and
- number of fingerprints in the template: FPCOUNT.
Embedding sensor information in template header means the template cannot mix fingerprints from multiple sources. Shared width and height complicates representation of multiple highly processed fingerprints, for example fused fingerprints.
File signature / magic number (MAGIC)
First four bytes of the template contain constant string "FMR\0" where '\0' stands for zero byte. This is a magic number (or file signature) that helps biometric software to automatically distinguish this format from other file formats. All later versions of this template format share the same magic number. Somewhat confusingly, ISO 19794-2 uses the same magic number.
Format version (VERSION)
Version field contains 4-byte constant string " 20\0" (note the space before "20") where '\0' stands for zero byte. Later versions of this format use different version string, which makes it easy to distinguish the versions.
Unfortunately, ISO 19794-2:2005 uses the same version string " 20\0". The only way to differentiate this format from ISO 19794-2:2005 is to look at the TOTALBYTES field. This is of course a totally ridiculous situation and it makes me question motivations of people designing these formats.
Total template length in bytes (TOTALBYTES)
Total length in bytes is redundant, because the template simply ends after the last FINGERPRINT section. It might be nevertheless useful to easily find the end of the template in a stream of bytes.
This field can be encoded in either 2 or 6 bytes and it may be a bit tricky to pick one option, because the field itself is part of total template length. Implementations should first try to store template length as a big-endian unsigned 16-bit number, assuming 2-byte TOTALBYTES field. If this fails, because the calculated length is more that 0xffff, the implementation should then use 6-byte encoding where the first two bytes are zero and the next 4 bytes carry big-endian unsigned 32-bit template length.
The original ANSI spec mandates encoding short lengths in 2 bytes, but it is a bit unclear about the boundary case around 0xffff. To maximize compatibility, this format summary recommends being tolerant during decoding. Template decoders should follow the following algorithm to read TOTALBYTES:
- Initially read only two bytes.
- If non-zero value is read, TOTALBYTES is assumed to be a big-endian unsigned 16-bit number.
- If the first two bytes are zero, TOTALBYTES is assumed to have the 6-byte form and decoders should read template length in the next 4 bytes as a big-endian unsigned 32-bit number.
TOTALBYTES smaller than 26 bytes is invalid, because it cannot accommodate even the template header.
Since MAGIC and VERSION are not sufficient to tell the difference between this format and ISO 19794-2:2005, TOTALBYTES must be used to augment format detection. In the ISO format, template length is always a big-endian unsigned 32-bit value that is no smaller than 24. The following algorithm can determine which one of the two template formats is being decoded:
- Read two bytes and interpret them as a big-endian unsigned 16-bit number A.
- If A is 26 or higher, the template is in this format and A is the value of the 2-byte form of TOTALBYTES. There's nothing more to read. Here we assume than no template in the ISO format will be larger than 1,703,935 bytes, which is unlikely to occur in practice.
- If A is in range 1-25, which is invalid in this format, the template is in the ISO format. Decoding should continue according to the ISO format.
- At this point, A is zero, because all other options have been already considered.
- Read two more bytes and interpret them as a big-endian unsigned 16-bit number B.
- If B is 24 or higher, a valid length in the ISO format, the template is assumed to be in the ISO format and B is its length. Decoding should continue according to the ISO format. Here we assume than no template in this format will be larger than 1,572,863 bytes, which is unlikely to occur in practice.
- The template is in this format and TOTALBYTES has the 6-byte form. Read two more bytes and interpret them as a big-endian unsigned 16-bit number C. Template length is 0x10000 * B + C.
Vendor ID (VENDOR)
A big-endian unsigned 16-bit number identifying the vendor of the sensor or application that produced the template. This field corresponds to the two most significant bytes of CBEFF Product ID. This field cannot be zero and it must contain valid vendor ID. Yes, you are reading that right: you cannot be just anybody to implement this format. You must be somebody, specifically somebody with a vendor ID.
You might be wondering where do you get such an ID? Well, this field could be just as well called "opensource disqualification field" or "small business handicap field" for the ridiculous cost of the ID. The original ANSI spec states the ID must be obtained from IBIA, an obscure industry association. IBIA will happily issue you this otherwise utterly useless ID for mere $500. Yes, you are reading that right. $500 to join the exclusive club of businesses that are allowed to create ANSI 378 templates. This has got to be the most entertaining field in the whole spec.
Luckily, Lisa Rajchel from ISO has registered vendor named "Vendor Unknown" with ID 0x103 (or 259 in decimal). I have no idea how "Vendor Unknown" came to be and how on Earth did IBIA allow it, but I guess ISO needed some fallback value in one of their own specs. Opensource, in-house, and small business implementations of this format are now free to use this loophole to avoid the ridiculous $500 fee. Aside from vendor ID 0x103 "Vendor Unknown", there is also vendor ID 0xfffe "Reserved for Testing", but that one is more likely to irritate some fussy decoders.
Vendor-specified subformat (SUBFORMAT)
A big-endian unsigned 16-bit number. The original ANSI spec is not entirely clear about the contents of this field, but author's understanding is that this is an extraction algorithm identifier tied to the vendor ID issued by IBIA as explained above under VENDOR field. The identifier doesn't have to be registered with IBIA since it's entirely vendor-defined. It effectively defines new subformat of this template format by indicating what features and extension blocks are included in the fingerprint template. Fortunately, this field can be left zeroed, which is the recommended practice for opensource implementations.
Sensor compliance (DEVSTAMP)
This field lives in the higher 4 bits of the byte it shares with DEVID field. Top bit indicates the fingerprint reader has certificate of compliance with Appendix F (IAFIS Image Quality Specifications) of CJIS-RS-0010 V7 (FBI's Electronic Fingerprint Transmission Specification, January 1999). Other bits are reserved. Opensource implementations should leave this field zeroed.
Sensor ID (DEVID)
Top 4 bits of this 12-bit field live in lower 4 bits of the byte this field shares with DEVSTAMP field. Remaining 8 bits are in the next byte. The 12-bit unsigned number is an ID of the fingerprint reader used to capture fingerprints in the template. Sensor IDs are assigned by the vendor identified in VENDOR field. Value of zero is allowed and it means unknown fingerprint reader. Opensource implementations should leave this field zeroed.
Image width (WIDTH)
Image width in pixels encoded as a big-endian unsigned 16-bit number.
Image height (HEIGHT)
Image height in pixels encoded as a big-endian unsigned 16-bit number.
Horizontal pixel density (RESOLUTIONX)
Image resolution (commonly called DPI), specifically its horizontal component, is stored in this field in units of pixels per centimeter. It is encoded as a non-zero big-endian unsigned 16-bit number. If sensor resolution is fractional, it is rounded to the nearest integer. The common resolution of 500dpi is equal to 197px/cm after rounding.
Vertical pixel density (RESOLUTIONY)
Number of fingerprints (FPCOUNT)
An unsigned 8-bit number that indicates the number of FINGERPRINT blocks in the template. FPCOUNT may be zero, in which case the template contains no fingerprints. The original ANSI spec states that this field's value range is 0-255, but since every fingerprint must have a unique combination of POSITION and VIEWOFFSET, there cannot be more than 11 x 16 = 176 fingerprints.
A single fingerprint view, essentially a single scan from fingerprint reader. Fingerprint section contains MINUTIA records and some metadata about the fingerprint, notably finger's POSITION on hands. Fingerprint section can optionally contain EXTENSION blocks, including ridge count data (RCOUNTEXT) and core/delta data (COREDELTA).
Single template can contain multiple FINGERPRINT sections. Their number is indicated by the FPCOUNT field. It is permitted to construct a template with no FINGERPRINT sections (zero FPCOUNT). Such template represents biometric system enrollee for whom fingerprint capture failed.
All fingerprint sections in the template must have unique combination of POSITION and VIEWOFFSET. If there are multiple FINGERPRINT sections with the same POSITION, then unique VIEWOFFSET is assigned to each and they must appear in the template ordered by VIEWOFFSET. The original ANSI spec doesn't require it, but it makes sense to list FINGERPRINT sections with the same POSITION together in the template.
Finger position on hands (POSITION)
An unsigned 8-bit number encoding hand position of the finger. It must be in range 0-10 with meaning of allowed codes explained by the table below.
Finger view number (VIEWOFFSET)
This unsigned 4-bit number is stored in the upper 4 bits of the byte it shares with MEDIATYPE field. If multiple fingerprints with the same POSITION are present in the template, unique VIEWOFFSET must be assigned to each, starting with zero and incrementing with each view of the same finger. If there is only one fingerprint with given POSITION, its VIEWOFFSET is zero. VIEWOFFSET's allowed range of 0-15 limits every finger position to 16 finger views. Finger views of one finger must be listed in the template in order of increasing VIEWOFFSET.
Sensor category (MEDIATYPE)
This unsigned 4-bit number, occupying lower 4 bits of the byte it shares with VIEWOFFSET, indicates how the fingerprint was captured. Contrary to the vendor-defined DEVID, this field is actually useful, because its values are specified. Matching algorithms can use this information to adjust error tolerances and other parameters. Allowed values in range 0-3 and 8-9 are described in the table below.
There is no reasonable default. Implementations that lack knowledge of the sensor type should use the most likely value 0 for live plain scan.
Fingerprint quality (FPQUALITY)
An 8-bit unsigned number indicating overall fingerprint quality. Note that there is also a per-minutia quality in the MINQUALITY field. Allowed values are in range 0-100 with 0 meaning lowest quality and 100 highest quality. The original spec references section 2.1.42 of ANSI/INCITS 358 as a guideline for choosing values for this field, but there is no clear specification for what these quality values mean, which makes them useless in matching. There is no special value for unknown or unreported quality in the original spec. This format summary recommends using quality 100 as a reasonable default.
Number of minutiae (MINCOUNT)
An unsigned 8-bit number that indicates the number of MINUTIA records that follow. MINCOUNT may be zero, which means the feature extractor failed to find any minutiae.
Minutiae are interesting points on the fingerprint, usually ridge endings and bifurcations.
MINUTIA records span 6 bytes each and carry minutia position (MINX, MINY), angle (MINANGLE), type (MINTYPE), and optionally quality (MINQUALITY). Field MINCOUNT contains the number of MINUTIA records present. There could be no MINUTIA records if the feature extractor failed to find any minutiae.
Minutia type (MINTYPE)
Minutia type is packed in the top two bits of the first byte occupied by the MINX field. Three minutia types are supported:
|00||Other minutia type|
The "other" minutia type (code 00) is for minutia types distinct from endings and bifurcations rather than for borderline cases where the minutia could be either an ending or a bifurcation.
Minutia X position (MINX)
Location of the minutia on the fingerprint in pixel units along X axis. Pixels are counted left-to-right, starting with zero. Minutia is in the center of the pixel specified by MINX and MINY.
MINX is a 14-bit unsigned number that is stored in the lower 14 bits of the big-endian 16-bit number that also contains MINTYPE.
In order to determine minutia position, feature extractor first constructs ridge skeleton by thinning ridges down to one pixel wide lines. Valley skeleton is constructed similarly by thinning valleys. Ridge endings lie at forking points of the valley skeleton. Similarly, ridge bifurcations lie at forking points of the ridge skeleton. Location of minutiae other than ending and bifurcation is implementation-specific.
Minutia Y position (MINY)
Like MINX above but for Y axis. Pixels on Y axis are counted top-down, starting with zero. MINY is stored in a 16-bit unsigned big-endian field, but only the lower 14 bits of this field are used for MINY. Upper 2 bits are zero.
Minutia angle (MINANGLE)
In order to keep angle calculations consistent across implementations, the original spec prescribes an algorithm for calculating the minutia angle, which is shown below. The algorithm describes calculation for ridge ending angle. Bifurcation angle is calculated similarly by swapping roles of ridge and valley skeletons.
- Consider ridge ending minutia positioned at forking point of the valley skeleton as described under MINX field above.
- Think of a vector and place its origin at the forking point.
- On the ridge skeleton, find the ridge end that corresponds to the minutia.
- This ridge endpoint becomes the target point of the vector.
- Convert the vector to mathematical angle that is zero when the vector points right and increases counterclockwise.
MINANGLE is an 8-bit unsigned number in range 0-179. Floating-point angle calculated above is quantized as follows.
- Convert angle units to floating-point degrees in range 0-360.
- Divide the angle by two.
- Round it up to integer value.
- If the result is 180, change it to 0 in order to keep the angle in range 0-179.
MINANGLE can be dequantized by reversing the process and centering the result in angle's quantization slot:
- Multiply the angle by two.
- Subtract one to center the angle in its quantization slot.
- If the result is -1, change it to 359 in order to keep the angle in range 0-360.
Angles for minutiae of type "other" are implementation-defined.
Minutia quality (MINQUALITY)
An 8-bit unsigned number encoding minutia quality from 1 (lowest quality) to 100 (highest quality). If minutia quality is not reported, this field is zero. Meaning of minutia quality depends on feature extractor that is identified in the SUBFORMAT field. Opensource implementations should set this field to zero.
Total length of extension data (EXTBYTES)
A big-endian 16-bit unsigned number holding the total size of all extensions in bytes. If EXTBYTES is zero, there are no extension blocks. If it is non-zero, one or more EXTENSION blocks follow. In that case, EXTBYTES is the sum of EXTLEN fields of all EXTENSION blocks.
Extension data block (EXTENSION)
If EXTBYTES is non-zero, one or more EXTENSION blocks are attached to the fingerprint. Every extension has two compulsory fields: EXTTYPE and EXTLEN. EXTLEN lets implementations skip over unrecognized extensions without having to parse them. EXTTYPE informs the implementation about internal structure of the extension, so that appropriate parser can be chosen. Actual extension data is stored in the EXTDATA field.
There are two predefined extensions: ridge count extension (RCOUNTEXT) and core and delta extension (COREDELTA). Extensions are intended to store data that cannot be expressed otherwise. Implementations must not abuse extensions to introduce alternative encoding for data that can be already encoded in documented fields of this format, including the predefined extensions.
Extension type (EXTTYPE)
Two bytes encode extension type according to the table below.
|Byte 1||Byte 2||Description|
|0||1||Ridge count extension (RCOUNTEXT)|
|0||2||Core and delta extension (COREDELTA)|
Implementation-defined extension codes are namespaced under VENDOR code. Since opensource implementations usually don't have assigned vendor ID, they should not include any custom extension blocks.
Length of extension data (EXTLEN)
Length of the whole EXTENSION block, including the EXTTYPE field and EXTLEN field itself, is stored in a big-endian 16-bit unsigned number. EXTLEN must be therefore at least 4. Implementations can use this field to skip over unrecognized extensions.
Extension data (EXTDATA)
Actual extension data. This field has length of EXTLEN minus the 4 bytes needed for EXTTYPE and EXTLEN. Internal structure of the EXTDATA field depends on the value of EXTTYPE field. This format specifies only structure of ridge count extension (RCOUNTEXT) and core and delta extension (COREDELTA).
Ridge count extension (RCOUNTEXT)
Minutia set defined in MINUTIA records can be annotated with ridge counts. Ridges are counted on a line (or edge) connecting two minutiae. Edge's ridge count is the number of ridges crossed by the edge as precisely defined in RIDGECOUNT field. RCOUNTEXT extension encodes this ridge count data. RCOUNTEXT has EXTTYPE of 0x0001.
Not all edges in the template need to have ridge count data.
Edge picking method is specified in STARTYPE field.
Information about every picked edge is then stored in EDGEDEF records that follow.
The number of EDGEDEF records can be derived from the length of this extension block (EXTLEN)
(EXTLEN - 5) / 3.
Ordering of EDGEDEF records depends on STARTYPE.
Edge picking method (STARTYPE)
This template format recognizes three edge picking methods: quadrants, octants, and custom. STARTYPE field contains an 8-bit unsigned code according to the table below.
Custom edge picking (code 0) simply means the implementation is free to choose edges however it wants. It can also choose how to order EDGEDEF records.
Quadrant (code 1) and octant (code 2) edge picking involves splitting the area around central minutia into four or eight sectors respectively. There are no restrictions on how the sectors are rotated relatively to the minutia. For every sector, ridge count is recorded for the edge to the nearest minutia in that sector. Quadrant and octant picking places strict requirements on presence, ordering, and contents of EDGEDEF records as explained below.
Edge between minutiae (EDGEDEF)
The 3-byte EDGEDEF record contains ridge count (stored in RIDGECOUNT field)
for a single edge between minutiae identified by EDGEFROM and EDGETO fields.
The number of EDGEDEF records is derived from EXTLEN as
(EXTLEN - 5) / 3.
Field STARTYPE determines which edges are present.
EDGEDEF record ordering depends on STARTYPE:
- If STARTYPE is custom (code 0), EDGEDEF records are ordered first by EDGEFROM and then by EDGETO.
- If STARTYPE is set to quadrants (code 1) or octants (code 2), EDGEDEF records for single central minutia are listed together. There are no other ordering constraints for neither central nor neighbor minutiae.
If STARTYPE is set to quadrants (code 1) or octants (code 2), the structure of EDGEDEF records is defined in more detail. EDGEFROM identifies the central minutia while EDGETO identifies the neighbor minutia. If some quadrant or octant does not have any minutiae, implementation must emit a placeholder record with EDGETO and RIDGECOUNT fields zeroed, thus padding edge list for every central minutia to four or eight records respectively.
Note that the original spec is unclear about the ordering of edges in ridge count extension. For maximum compatibility, template encoders should sort everything by EDGEFROM and then by EDGETO while decoders should accept arbitrary ordering. The original spec is also ambiguous as to whether quadrant and octant ridge picking (see STARTYPE) requires implementations to consider all minutiae as central minutiae or whether central minutiae can be picked arbitrarily. To be safe, encoders should include edges for all minutiae while decoders should accept edge information for a subset of all minutiae.
Starting minutia of the edge (EDGEFROM)
An 8-bit unsigned offset into the list of MINUTIA records. It identifies minutia that is on one end of the edge leading to EDGETO. If STARTYPE is quadrants (code 1) or octants (code 2), EDGEFROM is the central minutia.
Ending minutia of the edge (EDGETO)
An 8-bit unsigned offset into the list of MINUTIA records. It identifies minutia that is on the other end of the edge starting in EDGEFROM. If STARTYPE is quadrants (code 1) or octants (code 2), EDGETO is the neighbor minutia. If the current EDGEDEF record is a placeholder for quadrant or octant devoid of minutiae, EDGETO is zero.
Number of ridges the edge crosses (RIDGECOUNT)
Curved ridges may be crossed more than once. The original spec doesn't say how to handle such cases, but it is reasonable to count every ridge only once.
If the current EDGEDEF record is a placeholder for quadrant or octant devoid of minutiae, RIDGECOUNT is zero. Note that zero is a valid value for very short edges. Zeroed RIDGECOUNT is ambiguous if EDGETO is also zero. Since very short edges are rare, implementations can assume that zero RIDGECOUNT means placeholder EDGEDEF record.
Core and delta extension (COREDELTA)
Besides normal minutiae defined in MINUTIA records, this format permits encoding of cores and deltas, which can be thought of as very special minutiae. COREDELTA extension encodes information about cores and deltas found on the fingerprint. COREDELTA extension has EXTTYPE of 0x0002. COREDELTA extension has two parts: COREDATA and DELTADATA.
The original spec doesn't clearly define what is considered core or delta, but the common practice is as follows. Cores and deltas are points where no definite ridge direction can be determined. Core is a ridge vortex where ridges circle the core. Delta is recognized where three distinct ridge flows meet and the delta point doesn't clearly belong to any of them.
Core data (COREDATA)
COREDATA, the first part of COREDELTA extension, contains a list of cores found on the fingerprint. The original spec doesn't clearly define cores, but the common practice is to recognize core in a ridge vortex where ridges circle the core.
Core angle presence flag (CHASANGLE)
Number of cores (CORENUM)
Core point (COREDEF)
COREDEF describes one core found on the fingerprint. COREDEF record repeats CORENUM times. Its structure is somewhat similar to MINUTIA record. Every core has position (COREX, COREY). If CHASANGLE is set, every COREDEF also contains COREANGLE.
Core X position (COREX)
Equivalent of MINX for cores. The original spec doesn't define where core is positioned, but in the next version of this format, ANSI 378-2009, core is positioned in the focal point of the innermost ridge.
Core Y position (COREY)
Core angle (COREANGLE)
This field is present only if the CHASANGLE flag is set. It contains an angle encoded in the same way as MINANGLE, but its meaning is different. The original spec doesn't define what is core angle, but in the next version of this format, ANSI 378-2009, core angle points approximately in the average direction of ridges enveloping the core (except for circular whorl, which has no angle).
Delta data (DELTADATA)
DELTADATA, the second and last part of COREDELTA extension, contains a list of deltas found on the fingerprint. The original spec doesn't clearly define deltas, but the common practice is to recognize delta where three distinct ridge flows meet.
Delta angle presence flag (DHASANGLE)
This 1-bit field occupies bit 6 (lowest bit has number 0, highest 7) of the byte it shares with DELTANUM field. If it is set, three repeats of the DELTAANGLE field are present. If it is zero, no DELTAANGLE is recorded.
Number of deltas (DELTANUM)
Delta point (DELTADEF)
DELTADEF describes one delta found on the fingerprint. DELTADEF record repeats DELTANUM times. Its structure is somewhat similar to MINUTIA record. Every delta has position (DELTAX, DELTAY). If DHASANGLE is set, every DELTADEF also contains three repeats of the DELTAANGLE field.
Delta X position (DELTAX)
Equivalent of MINX for deltas. The original spec doesn't define where exactly is delta positioned.
Delta Y position (DELTAY)
Equivalent of MINY for deltas.
Delta angle (DELTAANGLE)
This field is present three times if DHASANGLE flag is set and zero times otherwise. The field contains an angle encoded in the same way as MINANGLE, but its meaning is different. The original spec doesn't define what are the three delta angles, but in the next version of this format, ANSI 378-2009, delta angles point in directions where two ridge flows meet.