Digital Surf Mountains MNT Format
This document describes the internal structure of the Digital Surf Mountains MNT file format, based on reverse engineering of example files.
Overview
The MNT format is used by Digital Surf’s Mountains software suite for storing surface topography data from profilometers, interferometers, and other surface measurement instruments. It is a Microsoft Compound Document File (OLE/COM structured storage) containing multiple streams.
File Structure
The file uses the OLE compound document format, identifiable by the magic bytes:
D0 CF 11 E0 A1 B1 1A E1
The file contains the following streams:
- ImagePreview
A JPEG image showing a preview of the topography. Note that this preview may include user interface elements and its aspect ratio does not necessarily match the actual data dimensions.
- ScopedContents
Binary stream containing the height data. This is the main data stream with a global header followed by zlib-compressed data blocks.
- ScopedResults
Parameter data and analysis results. The exact structure is not fully documented.
- XmlHeader
UTF-16 encoded XML metadata. Contains general file information (software version, serial number, operators) but does not store the data dimensions.
ScopedContents Structure
The ScopedContents stream uses a hierarchical TLV (Tag-Length-Value) encoding throughout. The entire stream can be traversed as a sequence of TLV entries.
TLV Entry Format
Each TLV entry has the following structure:
Field |
Type |
Description |
|---|---|---|
Tag |
uint16 LE |
Identifies the entry type |
Size |
uint64 LE |
Number of bytes in the data section |
Data |
variable |
The payload (size bytes, may contain nested TLV entries) |
Top-Level Structure
The stream begins with a size field followed by top-level TLV entries:
Offset 0x0000: uint64 LE - Total stream size minus 8 (integrity check)
Offset 0x0008: Tag 0x03, size=1 - Format version
Offset 0x0013: Tag 0x02, size=4 - Format flags
Offset 0x0021: Tag 0x04, size=8 - Timestamp or identifier
Offset 0x0033: Tag 0x05, size=8 - Contains dimension parameters
Offset 0x0045: Tag 0x01 - Main container (rest of stream)
The Tag 0x01 container holds all remaining data as nested TLV entries.
UTF-16 String Encoding
String values (e.g., serial numbers) have a type byte prefix:
Field |
Type |
Description |
|---|---|---|
Type byte |
uint8 |
Value 0x04 indicates a UTF-16 string |
String |
UTF-16 LE |
The string data (size - 1 bytes) |
Example: Serial number “DS-364280957” is encoded as:
cb 00 Tag 0xcb (serial number)
19 00 00 00 00 00 00 00 Size = 25 bytes
04 Type byte (string)
44 00 53 00 2d 00 ... UTF-16 LE "DS-364280957" (24 bytes)
Dimension Parameters
Key fields for calculating image dimensions are found at fixed byte offsets within the Tag 0x05 data block (offsets from start of ScopedContents):
Offset |
Type |
Description |
|---|---|---|
0x3d |
uint8 |
Number of compressed data blocks |
0x63 |
uint8 |
Rows factor A (first component of rows per block) |
0x71 |
uint8 |
Rows factor B (second component of rows per block) |
Height Data Container (Tag 0x02bd)
The height data is stored in a nested TLV structure within Tag 0x02bd:
Tag 0x02bd (height data container)
├── Tag 0x0001, size=1: num_blocks (e.g., 32)
└── Tag 0x0002 (compressed data container)
└── Tag 0x0001 (packed block data)
└── [16-byte prefix + zlib data] × num_blocks
Important: The innermost level does NOT use TLV encoding. The compressed blocks are packed sequentially with a fixed 16-byte prefix before each zlib stream.
Block Prefix Structure
Each compressed block is preceded by a 16-byte prefix with a fixed structure (not TLV):
Offset |
Type |
Description |
|---|---|---|
0-7 |
uint64 LE |
Element offset. Used to determine the correct ordering of blocks when reconstructing the height map. Blocks must be sorted by this value in ascending order. |
8-11 |
uint32 LE |
Elements per block. The number of height values (not bytes) contained in this block after decompression. |
12-15 |
uint32 LE |
Compressed size. The size in bytes of the following zlib-compressed data. |
The packed block format is:
[element_offset (8)] [elements_per_block (4)] [compressed_size (4)] [zlib data]
[element_offset (8)] [elements_per_block (4)] [compressed_size (4)] [zlib data]
... (repeated for each block)
Zlib Compression
The compressed data uses standard zlib compression. Common zlib header bytes:
78 01- No compression78 5E- Fast compression78 9C- Default compression78 DA- Best compression
Block Identification
Height data blocks can be identified by:
Finding all zlib-compressed blocks with substantial decompressed size (typically ≥50000 bytes for height data)
Grouping blocks by their
elements_per_blockvalueThe largest group of blocks with the same
elements_per_blockcontains the height data
Dimension Calculation
The image dimensions are calculated from header parameters and block metadata:
rows_per_block = header[0x63] × header[0x71]
width = elements_per_block / rows_per_block
height = num_blocks × rows_per_block
Where:
header[0x3d]is the number of blocks (num_blocks)header[0x63]is rows factor Aheader[0x71]is rows factor Belements_per_blockis read from the block prefix (bytes 8-11)
Example calculations:
File mnt-1.mnt:
num_blocks = 32
factor_a = 9, factor_b = 2
rows_per_block = 9 × 2 = 18
elements_per_block = 18000
width = 18000 / 18 = 1000
height = 32 × 18 = 576
Result: 1000 × 576
File mnt-2.mnt:
num_blocks = 32
factor_a = 10, factor_b = 3
rows_per_block = 10 × 3 = 30
elements_per_block = 38400
width = 38400 / 30 = 1280
height = 32 × 30 = 960
Result: 1280 × 960
Data Format
MNT files store height data as interleaved 16-bit signed integer pairs:
[height_0, secondary_0, height_1, secondary_1, height_2, secondary_2, ...]
Height values (even indices): 16-bit signed integers representing height in raw units
Secondary values (odd indices): May contain different types of data:
Validity flag: If only values 0 and -1 are present, this indicates validity (0 = valid, -1 = invalid/masked)
Other data: Some files contain small integer values (e.g., error estimates) in the secondary channel; these are ignored for height reconstruction
The data format is always 4 bytes per pixel (two int16 values), regardless of the secondary channel content.
Block Ordering
Important: Blocks may not appear in the file in the correct order for
reconstruction. The element_offset value (bytes 0-7 of each block prefix)
must be used to sort blocks before combining them.
Example block ordering:
Block 0: element_offset = 0 → First block (top of image)
Block 1: element_offset = 18000 → Second block
Block 2: element_offset = 36000 → Third block
...
The element offset indicates the starting position of each block’s data in the final reconstructed array.
Data Reconstruction
To reconstruct the height map:
Collect all height data blocks (identified by
elements_per_block)Sort blocks by their
element_offsetvalue (ascending)Concatenate the decompressed data in sorted order
Parse as int16 pairs: extract heights from even indices
Reshape to (height, width) and transpose to (width, height) for row-major storage
If the secondary channel contains only 0 and -1 values, create a mask where
secondary != 0indicates invalid data. Otherwise, mask only extreme int16 values (near ±32767).
Physical Units
The MNT format does not reliably store physical sizes or unit information in an easily accessible location. Users should:
Provide physical sizes manually when loading
Height values are in raw integer units; a scale factor may be needed
Example Files
mnt-1.mnt: Uses int16 pairs format. Dimensions: 1000 × 576. The secondary channel contains small integer values (not a validity flag), so only extreme int16 values (near ±32767) are masked. A small number of pixels (~316) have invalid data.
mnt-2.mnt: Uses int16 pairs format with validity flag in the secondary channel (0 = valid, -1 = invalid). Dimensions: 1280 × 960. Corner regions contain masked (invalid) data.
Known Limitations
Physical sizes must be provided by the user
Height scale factor not automatically extracted
The meaning of storing rows_per_block as two factors (A × B) is not understood
The complete TLV tag vocabulary is not documented; only tags observed in example files are described
References
The MNT format is proprietary to Digital Surf. This documentation is based on reverse engineering and may be incomplete or contain errors.