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.

Known Tags

Tags observed in example files:

Tag

Description

0x0001

Container/nested structure

0x0002-0x0005

Top-level metadata

0x00c8

Metadata block (variable size)

0x00c9

4-byte value

0x00ca

Metadata block (variable size)

0x00cb

Serial number string (UTF-16)

0x012d

Extended metadata

0x02bd

Height data container (contains compressed blocks)

0xffff

Marker/separator

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 compression

  • 78 5E - Fast compression

  • 78 9C - Default compression

  • 78 DA - Best compression

Block Identification

Height data blocks can be identified by:

  1. Finding all zlib-compressed blocks with substantial decompressed size (typically ≥50000 bytes for height data)

  2. Grouping blocks by their elements_per_block value

  3. The largest group of blocks with the same elements_per_block contains 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 A

  • header[0x71] is rows factor B

  • elements_per_block is 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:

  1. Collect all height data blocks (identified by elements_per_block)

  2. Sort blocks by their element_offset value (ascending)

  3. Concatenate the decompressed data in sorted order

  4. Parse as int16 pairs: extract heights from even indices

  5. Reshape to (height, width) and transpose to (width, height) for row-major storage

  6. If the secondary channel contains only 0 and -1 values, create a mask where secondary != 0 indicates 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.