GMP Container & Sub-Headers¶
This page describes the GMP container format, subfile organization, and all sub-headers (TRE, RGN, LBL, NET). For the outer file structure (header, FAT), see Header & FAT. For the tile data stored inside the GMP, see Tile Storage.
3. Subfile Organization¶
3.1 Subfile Types in Raster Maps¶
Raster IMG files can contain either 2 subfiles (single-map) or many subfiles (multi-map):
Single-map raster:
| Subfile | Type | Count | Description |
|---|---|---|---|
| GMP | Map | 1 | Main container with all raster data |
| MPS | Meta | 1 | Map source metadata (98 bytes) |
Multi-map raster (IOM format):
| Subfile | Type | Count | Description |
|---|---|---|---|
| GMP | Map | 51 | Each subfile covers a geographic tile |
| MPS | Meta | 1 | Map source metadata (3936 bytes) |
Subfile names in the FAT directory:
- GMP subfiles: map ID as 8-char uppercase hex (e.g.,
00355951) - MPS subfile:
MAPSOURC
3.1.1 Multi-Map Organization¶
Multi-map IMG files (like IOM.img) split the coverage area into multiple GMP subfiles, each representing one geographic tile. The MPS subfile contains reference records for all maps.
IOM.img example:
FAT entries: 51 GMP subfiles + 1 MPS subfile
Each GMP subfile: ~660KB with 8 zoom levels, covering ~7×5 km area
MPS subfile: 3936 bytes with L-records for all 51 maps
MPS multi-map reference format:
- Contains L-records listing all maps with Product ID (PID) and Family ID (FID)
- IOM.img: PID=1, FID=2150 for all 51 maps
Multi-map vs single-map parameter differences:
| Parameter | IOM (multi-map) | Single-map reference | cartoload output |
|---|---|---|---|
| Display priority | 20 | 24 | 20 |
| Parameters | 1 8 36 1 | 1 4 36 1 | 1 8 36 1 |
| TRE7 rec_size | 4 (simple) | 5 (extended) | 4 (simple + sentinel) |
| TRE8 entries | 2 | 1 | 2 |
| TRE5 data | None (size=0) | 3 bytes | None (size=0) |
| NET section | Not present | Present | Present (stub) |
3.2 GMP Container Format¶
The GMP subfile is a container that embeds standard Garmin sub-file headers (TRE, RGN, LBL, NET). This is the same format used by vector maps, but adapted for raster tiles.
GMP Container Layout:
[GMP Container Header: 53 bytes]
[Copyright strings: null-terminated]
[TRE Sub-Header: 273 bytes]
[Map Info Strings: "Raster Map\0" + copyright\0"]
[RGN Sub-Header: 125 bytes]
[LBL Sub-Header: 596 bytes]
[NET Sub-Header: 100 bytes]
[TRE Data Sections: copyright, subdivisions, map_levels]
[RGN Data Section: subdivision records]
[LBL Labels: tile filenames as null-terminated strings]
[Tile Index Table: N × uint32 offsets]
[JPEG Tile Data: concatenated JFIF JPEGs]
3.3 GMP Container Header (53 bytes)¶
| Offset | Size | Field | Value / Description |
|---|---|---|---|
| 0x00 | 1 | Header size | 0x35 (53) |
| 0x01 | 1 | Flag | 0x00 |
| 0x02 | 10 | Signature | GARMIN GMP |
| 0x0C | 2 | Version | 1 (uint16 LE) |
| 0x0E | 7 | Creation date | 7-byte Garmin date |
| 0x15 | 4 | Section table offset | 0 (sections start at end of header) |
| 0x19 | 28 | Section offsets | 7 × uint32 LE: TRE, RGN, LBL, NET, 0, 0, 0 |
3.4 Common Sub-Header Format (21 bytes)¶
All sub-section headers (TRE, RGN, LBL, NET) share a common 21-byte prefix:
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 2 | Header length | uint16 LE, total length of this sub-header |
| 2 | 10 | Type string | GARMIN TRE, GARMIN RGN, etc. |
| 12 | 1 | Version | Always 1 |
| 13 | 1 | Lock | 0 = unlocked |
| 14 | 7 | Date | 7-byte Garmin date |
3.5 TRE Sub-Header (273 bytes)¶
After the 21-byte common header, the TRE sub-header uses the following layout. All position values are GMP-relative offsets (see TRE Sections for complete field reference):
| Offset | Size | Field | Description |
|---|---|---|---|
| 21 | 3 | North bound | 3-byte signed LE, map units |
| 24 | 3 | East bound | 3-byte signed LE, map units |
| 27 | 3 | South bound | 3-byte signed LE, map units |
| 30 | 3 | West bound | 3-byte signed LE, map units |
| 33 | 4 | Map levels position | uint32 LE, GMP-relative (see TRE1 Map Levels) |
| 37 | 4 | Map levels size | uint32 LE |
| 41 | 4 | Subdivisions position | uint32 LE, GMP-relative (see TRE2 Subdivisions) |
| 45 | 4 | Subdivisions size | uint32 LE |
| 49 | 4 | Copyright position | uint32 LE, GMP-relative |
| 53 | 4 | Copyright size | uint32 LE |
| 57 | 2 | Copyright item size | uint16 LE (typically 3) |
| ... | ... | Remaining fields | See TRE Header Structure for complete TRE header map |
3-byte signed map units: degrees × 2^24 / 360. For example, latitude 47.65°:
Display priority: 20 (matching IOM reference, optimal for raster basemaps).
3.6 RGN Sub-Header (125 bytes)¶
After the 21-byte common header, the RGN sub-header uses the following layout. All position values are GMP-relative offsets. Field values are from the Oppmann PDF spec (2023-09-05) and verified against reference files.
| RGN Offset | Size | Field | Description / Reference Value |
|---|---|---|---|
| 0x15 | 4 | RGN1 position | GMP-relative offset to section 1 data |
| 0x19 | 4 | RGN1 size | Size of section 1 in bytes |
| 0x1D | 4 | RGN2 position | GMP-relative offset to polygon/raster section |
| 0x21 | 4 | RGN2 size | Size of polygon section in bytes |
| 0x25 | 4 | RGN2 ext: encoding flag | Known values: 0, 2. Must be 2 for extended/raster maps. |
| 0x29 | 4 | RGN2 ext: flags[0] | 0x00000000 (always zero) |
| 0x2D | 4 | RGN2 ext: flags[1] | 0x200000FF — polygon local flag bitmask |
| 0x31 | 4 | RGN2 ext: flags[2] | 0x0003FCFD — polygon local flag bitmask |
| 0x35 | 4 | RGN2 ext: flags[3] | 0x00000000 (always zero) |
| 0x39 | 4 | RGN3 position | GMP-relative offset to polyline section (= rgn2_pos + rgn2_size) |
| 0x3D | 4 | RGN3 size | 0 for raster maps |
| 0x41 | 4 | RGN3 ext: reserved | 0x00000000 |
| 0x45 | 4 | RGN3 ext: flags[0] | 0x00000000 |
| 0x49 | 4 | RGN3 ext: flags[1] | 0x2000003F — lines local flag bitmask |
| 0x4D | 4 | RGN3 ext: flags[2] | 0x00000FFD — lines local flag bitmask |
| 0x51 | 4 | RGN3 ext: flags[3] | 0x00000000 |
| 0x55 | 4 | RGN4 position | GMP-relative offset to POI section (= rgn2_pos + rgn2_size) |
| 0x59 | 4 | RGN4 size | 0 for raster maps |
| 0x5D | 4 | RGN4 ext: reserved | 0x00000000 |
| 0x61 | 4 | RGN4 ext: flags[0] | 0x00000000 |
| 0x65 | 4 | RGN4 ext: flags[1] | 0x20003FFF — points local flag bitmask |
| 0x69 | 4 | RGN4 ext: flags[2] | 0x0FFFF73F — points local flag bitmask |
| 0x6D | 4 | RGN4 ext: flags[3] | 0x00000000 |
| 0x71 | 4 | RGN5 position | GMP-relative offset to dictionary section (= rgn2_pos + rgn2_size) |
| 0x75 | 4 | RGN5 size | 0 for raster maps |
| 0x79 | 4 | RGN5 ext: dict info | 1 (controls Huffman table loading) |
Critical field: RGN+0x25. The value 2 at this offset indicates extended polygon encoding. Without this field set correctly, Garmin device firmware will not parse the RGN2 section as extended/raster data. A value of 0 means standard (non-extended) polygon format.
Local flag bitmasks: The flags fields at 0x2D, 0x31, 0x49, 0x4D, 0x65, 0x69 are bitmasks that tell the device firmware which extended object types (type values >= 0x100) have local fields in each section.
Section positions for empty sections: RGN3, RGN4, and RGN5 positions are set to rgn2_pos + rgn2_size (immediately after the RGN2 data) with size=0, indicating no polyline, POI, or dictionary data.
3.7 LBL Sub-Header (596 bytes)¶
After the 21-byte common header:
| Offset | Size | Field | Description |
|---|---|---|---|
| 21 | 4 | Labels position | uint32 LE, relative to LBL start |
| 25 | 4 | Labels size | uint32 LE |
| 29 | 1 | Offset multiplier | 1 |
| 30 | 1 | Encoding | 9 (8-bit, 1 byte per character) |
| 31+ | ... | Remaining fields | Places section, codepage, sort IDs |
| 0xAA | 2 | Codepage | uint16 LE, 1252 (Windows Western European) |
Labels content: Tile filenames as null-terminated strings (e.g., "0.jpg", "1.jpg", ...).
3.8 NET Sub-Header (100 bytes)¶
Minimal stub for raster maps. Contains the 21-byte common header, with all NET-specific fields set to zero (no network/routing data needed for raster maps).
10. Reference File Analysis¶
10.1 IOM.img (Isle of Man, Multi-Map Raster)¶
| Property | Value |
|---|---|
| File size | 33,462,272 bytes (31.9 MB) |
| Block size | 2,048 bytes (E1=0x09, E2=0x02) |
| Subfiles | 51 GMP + 1 MPS (multi-map format) |
| Map name | OS Map - Isle of Man |
| Map ID | PID=1, FID=2150 |
| Zoom levels | 8 levels per subfile (level 0x87 to 0x00, zoom 17-24) |
| Display priority | 20 |
| TRE7 rec_size | 4 (simple uint32 offsets) |
| TRE8 entries | 2 (raster tiles + DATA_BOUNDS) |
| RGN5 | 112 bytes (starts with DF 14 06 02 20 0B) |
| NET section | Not present |
Primary analysis target: Subfile 00355951 — fully validated against QMapShack wiki analysis by Alex Whiter.
10.2 Single-Map Raster Reference¶
| Property | Value |
|---|---|
| File size | 1,495,072,768 bytes (1.39 GB) |
| Header date | 16.04.2022 15:03:56 |
| Map name | Svizzera_W Raster Map |
| Map ID | 09C102B0 |
| FAT | 1000h - 1200h - 20000h, block 32768 |
| Zoom levels | [20,21,22,23,24], zoom [84,83,2,1,0] |
| Bitmaps | 32,443 tiles, ~1.49 GB |
| Subfiles | 2 (GMP + MPS) |
| Display priority | 24 |
| TRE7 rec_size | 5 (uint32 + 1 byte flag) |
| TRE8 entries | 1 (raster tiles only) |
| RGN5 | 0 bytes (not present) |
| NET section | Present |
10.3 Single-Map Raster Reference (East)¶
| Property | Value |
|---|---|
| File size | 1,421,049,856 bytes (1.32 GB) |
| Header date | 20.04.2022 17:10:22 |
| Map name | Svizzera_E Raster Map |
| Map ID | 013202B4 |
| FAT | 1000h - 1200h - 18000h, block 32768 |
| Bitmaps | 28,737 tiles, ~1.42 GB |
10.4 Our Implementation Output¶
| Property | Value |
|---|---|
| GMT validation | Exit code 0 (pass) |
| Single-tile IMG | 98,304 bytes, GMT reads correctly |
| Multi-tile IMG | 98,304 bytes (3 zooms, 21 tiles), passes |
| GMP subfile name | Map ID as hex (e.g., "09C102B0") |
| Character encoding | CP-1252 |
| Display priority | 20 (matches IOM reference) |
| TRE7 rec_size | 4 (uint32 offset only + sentinel) |
| TRE8 entries | 2 (polyline 0x06 + polygon 0x0D) |
| TRE5 data | None (size=0) |
| TRE parameters | 10 01 08 24 00 01 00 00 (matches IOM) |
12. Format Variant Recommendation¶
12.1 Comparison: Single-Map vs Multi-Map Raster IMG¶
Based on analysis of both reference files, there are two distinct raster IMG format variants:
| Aspect | Single-Map (reference) | Multi-Map (IOM) | Our Output |
|---|---|---|---|
| GMP subfiles | 1 | 51 (one per geographic tile) | 1 (single-map format) |
| MPS subfile | 98 bytes | 3,936 bytes (L-records for all) | 98 bytes |
| File complexity | Low — single container | High — FAT chain traversal needed | Low — single container |
| TRE7 rec_size | 5 (extended) | 4 (simple) | 4 (simple + sentinel) |
| TRE8 entries | 1 | 2 | 2 |
| TRE5 data | 3 bytes | None (size=0) | None (size=0) |
| RGN5 section | Absent (size=0) | Present (112 bytes) | Absent (size=0) |
| NET section | Present | Absent | Present (stub) |
| bits_field | 0x2D (2-byte index) | 0x2B (1-byte index) | Variable (depends on tile count) |
| Max tiles per subfile | 32,000+ | < 256 per subfile | 32,000+ |
| Block size | 32,768 | 2,048 | 32,768 |
| Display priority | 24 | 20 | 20 |
| TRE parameters | 00 01 04 24 00 01 00 00 |
10 01 08 24 00 01 00 00 |
10 01 08 24 00 01 00 00 |
| Cross-reference | None needed | MPS L-records required | None needed |
| Documentation coverage | Complete (all sections parsed) | Complete (validated against wiki) | Complete |
12.2 Recommendation: IOM-Compatible Format¶
Our implementation targets the IOM parameter set within a single-GMP container. Rationale:
-
Device compatibility: The IOM parameter set (priority 20, TRE7 rec_size=4, TRE8 with 2 entries, TRE parameters
10 01 08 24) is proven to work on Garmin devices for both multi-map and single-map configurations. The single-map parameter set uses a different TRE7 format (rec_size=5 with flag bytes) that is less well understood. -
GPXSee compatibility: The TRE7 rec_size=4 format with
_flags=0x01is cleanly parsed by GPXSee: it reads exactly 4 bytes per entry (polygon offset only) and uses the sentinel entry forsetExtEnds(). -
Simplicity: Single GMP container = no FAT chain traversal, no multi-map MPS coordination. The writer generates exactly 2 subfiles (1 GMP + 1 MPS).
-
Scalability: A single GMP container handles 32,000+ tiles with no subfile splitting logic. The FAT system handles multi-part GMP subfiles automatically.
-
Documentation coverage: All sections are fully understood — TRE1 through TRE10, RGN1-RGN5, LBL1/LBL28/LBL29. Validated against both IOM reference and GPXSee source code.
-
Implementation path: Our writer uses single-map container format with IOM-compatible TRE parameters, confirmed working on GPXSee and Garmin devices.
When to consider multi-map format: Only if targeting very small block sizes (2,048 bytes) or if Garmin device compatibility testing reveals that multi-map is required for specific use cases. For all typical raster map use cases, single-map is preferred.