PMTiles -- ProtoMaps Tiles
Added in version 3.8.
Driver short name
PMTiles
Driver built-in by default
This driver is built-in by default
This driver supports reading and writing PMTiles datasets containing vector tiles, encoded in the MapVector Tiles (MVT) format.
PMTiles is a single-file archive format for tiled data. A PMTiles archive can be hosted on a commodity storage platform such as S3, and enables low-cost, zero-maintenance map applications that are "serverless" - free of a custom tile backend or third party provider.
This driver is compatible with all GDAL network-based virtual file systems
The SRS is always the Pseudo-Mercator (a.k.a Google Mercator) projection, EPSG:3857.
The supported datasets must contain a JSON metadata document
following the
MBTiles specification,
containing at least the vector_layers
array.
Note that the driver will make no effort of stitching together geometries for linear or polygonal features that overlap several tiles. An application that wishes to eliminate those interrupts could potentially use the CLIP=NO open option to get larger boundaries, and use appropriate clipping graphic primitives to hide those discontinuities.
Driver capabilities
Supports Create()
This driver supports the GDALDriver::Create()
operation
Supports Georeferencing
This driver supports georeferencing
Supports VirtualIO
This driver supports virtual I/O operations (/vsimem/, etc.)
Opening options
Open options can be specified in command-line tools using the syntax -oo <NAME>=<VALUE>
or by providing the appropriate arguments to GDALOpenEx()
(C) or gdal.OpenEx
(Python).
The following open options are available:
CLIP=[YES/NO]: Defaults to
YES
. Whether to clip geometries of vector features to tile extent.Vector tiles are generally produced with a buffer that provides overlaps between adjacent tiles, and can be used to display them properly. When using vector tiles as a vector layer source, like in OGR vector model, this padding is undesirable, hence the default behavior of clipping.
ZOOM_LEVEL=<integer>: Zoom level to use. Must be between the minimum and maximum zoom levels reported in the metadata. Defaults to the maximum zoom level available in the dataset.
ZOOM_LEVEL_AUTO=[YES/NO]: Defaults to
NO
. Whether to auto-select the zoom level for vector layers according to the spatial filter extent. Only for display purpose.JSON_FIELD=[YES/NO]: Defaults to
NO
. Whether tile attributes should be serialized in a singlejson
field as JSON. This may be useful if tiles may have different attribute schemas.
Creation issues
Tiles are generated with WebMercator (EPSG:3857) projection. Several layers can be written. It is possible to decide at which zoom level ranges a given layer is written.
Part of the conversion is multi-threaded by default, using as many
threads as there are cores. The number of threads used can be controlled
with the GDAL_NUM_THREADS
configuration option.
The driver implements also a direct translation mode when using ogr2ogr
with a MBTiles vector dataset as input and a PMTiles output dataset, without
any argument: ogr2ogr out.pmtiles in.mbtiles
. In that mode, existing MVT
tiles from the MBTiles files are used as such, contrary to the general writing
mode that will involve computing them by discretizing geometry coordinates.
Dataset creation options
Dataset creation options can be specified in command-line tools using the syntax -dsco <NAME>=<VALUE>
or by providing the appropriate arguments to GDALCreate()
(C) or Driver.Create
(Python).
The following dataset creation options are supported:
NAME=value: Tileset name. Defaults to the basename of the output file/directory. Used to fill metadata records.
DESCRIPTION=value: A description of the tileset. Used to fill metadata records.
TYPE=[overlay/baselayer]: Layer type. Used to fill metadata records.
MINZOOM=<integer>: Defaults to
0
. Minimum zoom level at which tiles are generated.MAXZOOM=<integer>: Defaults to
5
.Maximum zoom level at which tiles are generated. Maximum supported value is 22.
CONF=[<json>/<filename>]: Layer configuration as a JSON serialized string. Or filename containing the configuration as JSON.
SIMPLIFICATION=float: Simplification factor for linear or polygonal geometries. The unit is the integer unit of tiles after quantification of geometry coordinates to tile coordinates. Applies to all zoom levels, unless
SIMPLIFICATION_MAX_ZOOM
is also defined.SIMPLIFICATION_MAX_ZOOM=<float>: Simplification factor for linear or polygonal geometries, that applies only for the maximum zoom level.
EXTENT=<positive integer>: Defaults to
4096
. Number of units in a tile. The greater, the more accurate geometry coordinates (at the expense of tile byte size).BUFFER=<positive integer>: Number of units for geometry buffering. This value corresponds to a buffer around each side of a tile into which geometries are fetched and clipped. This is used for proper rendering of geometries that spread over tile boundaries by some rendering clients. Defaults to 80 if
EXTENT=4096
.MAX_SIZE=<integer>: Defaults to
500000
. Maximum size of a tile in bytes (after compression). If a tile is greater than this threshold, features will be written with reduced precision, or discarded.MAX_FEATURES=<integer>: Defaults to
200000
. Maximum number of features per tile.
Layer configuration
The above mentioned CONF dataset creation option can be set to a string whose value is a JSON serialized document such as the below one:
{
"boundaries_lod0": {
"target_name": "boundaries",
"description": "Country boundaries",
"minzoom": 0,
"maxzoom": 2
},
"boundaries_lod1": {
"target_name": "boundaries",
"minzoom": 3,
"maxzoom": 5
}
}
boundaries_lod0 and boundaries_lod1 are the name of the OGR layers that are created into the target MVT dataset. They are mapped to the MVT target layer boundaries.
It is also possible to get the same behavior with the below layer creation options, although that is not convenient in the ogr2ogr use case.
Layer creation options
Layer creation options can be specified in command-line tools using the syntax -lco <NAME>=<VALUE>
or by providing the appropriate arguments to GDALDatasetCreateLayer()
(C) or Dataset.CreateLayer
(Python).
The following layer creation options are supported:
MINZOOM=<integer>: Minimum zoom level at which tiles are generated. Defaults to the dataset creation option
MINZOOM
value.MAXZOOM=<integer>: Maximum zoom level at which tiles are generated. Defaults to the dataset creation option
MAXZOOM
value. Maximum supported value is 22.NAME=value: Target layer name. Defaults to the layer name, but can be overridden so that several OGR layers map to a single target layer. The typical use case is to have different OGR layers for mutually exclusive zoom level ranges.
DESCRIPTION=value: A description of the layer.
/vsipmtiles/ virtual file system
The /vsipmtiles/ virtual file system offers a view of the content of a PMTiles dataset has a file hierarchy, with the following structure:
/pmtiles_header.json: JSON view of the PMTiles header
/metadata.json: JSON metadata document stored in the dataset
/{z}/: Directory with tiles for zoom level z
/{z}/{x}/: Directory with tiles for zoom level z and x
/{z}/{x}/{y}.{ext}: Tile data
The gdal_ls.py and gdal_cp.py sample utilities can be used to explore and extract data from a PMTiles dataset
Listing the content of a dataset:
python gdal_ls.py -lr "/vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles"
outputs:
-r--r--r-- 1 unknown unknown 809 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/pmtiles_header.json
-r--r--r-- 1 unknown unknown 1872 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/metadata.json
dr-xr-xr-x 1 unknown unknown 0 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/0/
dr-xr-xr-x 1 unknown unknown 0 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/0/0/
-r--r--r-- 1 unknown unknown 588 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/0/0/0.mvt
dr-xr-xr-x 1 unknown unknown 0 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/1/
dr-xr-xr-x 1 unknown unknown 0 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/1/1/
-r--r--r-- 1 unknown unknown 590 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/1/1/0.mvt
[ ... snip ... ]
-r--r--r-- 1 unknown unknown 771 2023-05-29 09:06 /vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/14/8707/5974.mvt
Displaying the metadata JSON file:
python swig/python/gdal-utils/osgeo_utils/samples/gdal_cp.py "/vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles/metadata.json" /vsistdout/ | jq .
outputs:
{
"attribution": "<a href=\"https://protomaps.com\" target=\"_blank\">Protomaps</a> © <a href=\"https://www.openstreetmap.org\" target=\"_blank\"> OpenStreetMap</a>",
"name": "protomaps 2023-01-18T07:49:39Z",
"type": "baselayer",
"vector_layers": [
{
"fields": {},
"id": "earth"
},
{
"fields": {
"boundary": "string",
"landuse": "string",
"leisure": "string",
"name": "string",
"natural": "string"
},
"id": "natural"
},
{ "... snip ...": {} },
{
"fields": {
"pmap:min_admin_level": "number"
},
"id": "boundaries"
},
{
"fields": {},
"id": "mask"
}
]
}
Extracting all content in a local directory:
python swig/python/gdal-utils/osgeo_utils/samples/gdal_cp.py -r "/vsipmtiles//vsicurl/https://protomaps.github.io/PMTiles/protomaps(vector)ODbL_firenze.pmtiles" out_pmtiles
Examples
Simple translation of a single shapefile into PMTiles. Dataset creation options (dsco) MINZOOM and MAXZOOM specifies tile zoom levels.
ogr2ogr -dsco MINZOOM=10 -dsco MAXZOOM=20 -f "PMTiles" filename.pmtiles my_shapes.shp
Merge all PostgreSQL/PostGIS tables in a schema into a single PMTiles file. PostgreSQL table names are used as layer names. Dataset creation options (dsco) MINZOOM and MAXZOOM specifies tile zoom levels.
ogr2ogr -dsco MINZOOM=0 -dsco MAXZOOM=22 -f "PMTiles" filename.pmtiles "PG:host=my_host port=my_port dbname=my_database user=my_user password=my_password schemas=my_schema"