1. Preamble
This document defines the VersaTiles Container Format v2.0, which describes the structure and encoding mechanisms for efficiently storing large numbers of map tiles.
2. General Guidelines
- Byte order: All numeric values are encoded in big-endian byte order.
- Tile organisation: Tiles are organised according to the XYZ scheme, with the origin (x=0, y=0) at the top left (northwest) corner.
3. File Structure
The VersaTiles container format consists of four main components:
- File Header: Introduces the container file, details its global properties, and indicates the locations of the Metadata and Block Index.
- Metadata: Provides detailed information about the tileset, including attribution and layer definitions.
- Blocks: Aggregates tiles into larger units (Blocks) for efficient storage and access, each containing Tile Blobs and Tile Index.
- Block Index: Acts as a parent directory for all blocks within the file.
| File Format |
|---|
 |
- Length: 66 bytes.
- Position: At the beginning of the file.
- Purpose: Outlines essential file properties and indicates subsequent section locations.
- All offsets are relative to the beginning of the file.
| Offset | Length | Type | Description |
|---|
| 0 | 14 | string | File identifier ("versatiles_v02") |
| 14 | 1 | u8 | tile_format value |
| 15 | 1 | u8 | precompression value |
| 16 | 1 | u8 | minimum zoom level |
| 17 | 1 | u8 | maximum zoom level |
| 18 | 4 | i32 | bbox min x (10⁷ × lon) |
| 22 | 4 | i32 | bbox min y (10⁷ × lat) |
| 26 | 4 | i32 | bbox max x (10⁷ × lon) |
| 30 | 4 | i32 | bbox max y (10⁷ × lat) |
| 34 | 8 | u64 | offset of Metadata |
| 42 | 8 | u64 | length of Metadata |
| 50 | 8 | u64 | offset of Block Index |
| 58 | 8 | u64 | length of Block Index |
| Value hex | Value dec | Type | Mime |
|---|
0x00 | 0 | bin | application/octet-stream |
0x10 | 16 | png | image/png |
0x11 | 17 | jpg | image/jpeg |
0x12 | 18 | webp | image/webp |
0x13 | 19 | avif | image/avif |
0x14 | 20 | svg | image/svg+xml |
0x20 | 32 | pbf | application/x-protobuf |
0x21 | 33 | geojson | application/geo+json |
0x22 | 34 | topojson | application/topo+json |
0x23 | 35 | json | application/json |
3.1.2. Value precompression
Metadata and all Tile Blobs are pre-compressed with:
| Value | Method |
|---|
0 | Uncompressed |
1 | gzip |
2 | Brotli |
- Content: Encapsulates
tiles.json, detailing tileset metadata. - Encoding: UTF-8.
- Compression: Defined by the
precompression flag in the File Header. - Note: The absence of Metadata is indicated by zero offsets and lengths in the File Header.
3.3. Blocks
- Structure: Blocks act as aggregators for up to 256×256 tiles.
- Zoom Levels: Individual Blocks can span entire zoom levels (0-8). Higher zoom levels (>8) may require multiple Blocks.
- Maximum number of Blocks per zoom level:
pow(4, max(0, level - 8)).
| Blocks per level |
|---|
 |
- Each Block contains concatenated Tile Blobs and ends with a Tile Index.
- Neither the Tile Blobs in a Block nor the Blocks in the file need to follow any particular order.
3.3.1. Tile Blobs
- Tile Blobs are concatenated binary data, each containing one tile. All tiles have the same format and are pre-compressed.
- Format: Each Tile Blob has the same file format, determined by the
tile_format code in the File Header. - Compression: Each Tile Blob is compressed according to the
precompression flag in the File Header.
3.3.2. Tile Index
- Compression: Brotli.
- Purpose: Maps the coordinates of tiles within a block to their respective binary position and length.
- Tiles are ordered horizontally, then vertically
index = (row - row_min) * (col_max - col_min + 1) + (col - col_min)- (
col_min, row_min, col_max, row_max are specified in Block Index) - Identical Tile Blobs can be stored once and referenced multiple times to save storage space.
- If a tile does not exist, the length of the Tile Blob is
0. - The offsets of Tile Blobs are relative to the beginning of the Block. So the offset of the first Tile Blob should always be
0.
| Offset | Length | Type | Description |
|---|
| 12*i | 8 | u64 | offset of Tile Blob in Block |
| 12*i+8 | 4 | u32 | length of Tile Blob |
| index of Tile Blobs |
|---|
 |
3.4. Block Index
- Compression: Brotli.
- Function: Provides a directory for locating Blocks within the container file.
- Empty Blocks are not saved.
- Each 33-byte entry within the Block Index is structured as follows:
| Offset | Length | Type | Description |
|---|
| 0 + 33*i | 1 | u8 | level |
| 1 + 33*i | 4 | u32 | column/256 |
| 5 + 33*i | 4 | u32 | row/256 |
| 9 + 33*i | 1 | u8 | col_min (0..255) |
| 10 + 33*i | 1 | u8 | row_min (0..255) |
| 11 + 33*i | 1 | u8 | col_max (0..255) |
| 12 + 33*i | 1 | u8 | row_max (0..255) |
| 13 + 33*i | 8 | u64 | offset of Block in file |
| 21 + 33*i | 8 | u64 | length of Tile Blobs |
| 29 + 33*i | 4 | u32 | length of Tile Index |
- Since a Block consists only of Tile Blobs appended by a Tile Index, the length of Block must be the sum of the lengths of the Tile Blobs and the Tile Index.
- Note: To efficiently find the Block containing the tile you are looking for, use a data structure such as a "map", "dictionary" or "associative array" and fill it with the data from the Block Index.
4. Glossary
- Blob: A chunk of binary data. Object storage on Wikipedia
- Block: A composite unit containing up to 256×256 tiles.
- Brotli: A compression algorithm known for its efficiency and performance. It provides better compression than gzip. Brotli on Wikipedia
- Tile: A square geographic area at a given zoom level containing map information as an image or as vector data.