Cloud-optimized, single-file archive format for pyramids of map tiles

Overview

PMTiles

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.

Demo - watch your network request log

See also:

How To Use

Python library: pip install pmtiles

pmtiles-convert TILES.mbtiles TILES.pmtiles
pmtiles-convert TILES.pmtiles DIRECTORY
pmtiles-show TILES.pmtiles // see info about a PMTiles directory
pmtiles-serve TILES.pmtiles // start an HTTP server that decodes PMTiles into traditional Z/X/Y paths

See https://github.com/protomaps/PMTiles/tree/master/python/bin for library usage

JavaScript usage:

Include the script:

<script src="https://unpkg.com/[email protected]/pmtiles.js"></script>

Example of a raster PMTiles archive decoded and displayed in Leaflet:

const p = new pmtiles.PMTiles('osm_carto.pmtiles',{allow_200:true})
p.leafletLayer({attribution:'© <a href="https://openstreetmap.org">OpenStreetMap</a> contributors'}).addTo(map)

Specification

A detailed specification is forthcoming. PMTiles is a binary serialization format designed for two main access patterns: over the network, via HTTP 1.1 Byte Serving (Range: requests), or via memory-mapped files on disk.

Design considerations

  • Directories are recursive, with a maximum of 21,845 entries per directory.
    • 21845 is the total tiles of a pyramid with 8 levels, or 1+4+16+64+256+1024+4096+16384
  • Deduplication of tile data is handled by multiple entries pointing to the same offset in the archive.
  • The order of tile data in the archive is unspecified; an optimized implementation should arrange tiles on a 2D space-filling curve.

Details

  • The first 512,000 bytes of a PMTiles archive are reserved, and contain the headers as well as a root directory.
  • All integer values are little-endian.
  • The headers begin with a 2-byte magic number, "PM"
  • 2 bytes: the PMTiles specification version, right now always 1.
  • 4 bytes: the length of metadata (M bytes)
  • 2 bytes: the number of entries in the root directory (N)
  • M bytes: the metadata, by convention a JSON object.
  • N * 17 bytes: the root directory.

Directory structure

A directory is a sequence of 17 byte entries. An entry consists of:

  • 1 byte: the zoom level (Z) of the entry, with the top bit set to 1 instead of 0 to indicate the data is a child directory, not tile content.
  • 3 bytes: the X (column) of the entry.
  • 3 bytes: the Y (row) of the entry.
  • 6 bytes: the offset of where the data begins in the archive.
  • 4 bytes: the length of the data.

License

The reference implementations of PMTiles are published under the BSD 3-Clause License. The PMTiles specification itself is public domain, or under a CC0 license where applicable.

Comments
  • Alternative dir structure for a more compact storage and proximity clustering

    Alternative dir structure for a more compact storage and proximity clustering

    I would like to propose some changes to the directory structure, but these might be totally irrelevant due to my misunderstanding.

    Current directory entry is fixed at 17bytes, stores x,y as individual values, and requires x,y sorting order. I think all of those may benefit from a bit of restructuring:

    • Combine x and y values into a single interleaved value (z-curve). This will make tiles more locale-clustered, possibly reducing the number of range requests (web).
    • Make the combined x,y value size depend on the zoom level, rounding to the nearest byte boundary. zooms 0..3 -- 1 byte, 4..7 -- 2 bytes, etc. All leaf nodes are required to be the same zoom, making the directory entries the same size only inside a single directory block, rather than everywhere.
    • For the root dir, it could still be 17bytes (although it seems 6 bytes is a bit too much -- zoom 16..19 only requires 5 bytes, so unless pmtiles wants to support more... and even that can be made flex)
    v3 
    opened by nyurik 41
  • Using python Reader object with cloud storage

    Using python Reader object with cloud storage

    It seems like go-pmtiles is set up to read from cloud storage (S3, Google Storage etc), but the python version here is not. Is that correct? How hard would it be to add that? I use Google, but an S3 example would be great.

    If the Reader API is robust, I can add it into a flask/fastapi endpoint pretty trivially, implement my own authentication etc, but it definitely seems like being able to read the tiles from a file in Storage (rather than locally) is the really powerful use case here.

    opened by fscottfoti 12
  • js: slow to load due to no network parallelism

    js: slow to load due to no network parallelism

    When using pmtiles.js, network performance is a big bottleneck.

    This is visible in the leaflet raster demo but mitigated by a very fast backend (read from a small pmtiles file), so response-time is ~15ms per tile. Still you can see in the chrome dev tools that each fetch request is "stalled" (queued) until the previous one is answered.

    My setup responds in ~150ms per tile, so time from scrolling to display is several seconds.

    How can this be optimised?

    • Reducing number of requests using Multipart Ranges does not seem possible without adding complexity to the leaflet integration.
    • ... but according to chrome we're supposed to have up to 6 concurrent TCP connections per origin?
    opened by eddy-geek 11
  • Compression (spec v3)

    Compression (spec v3)

    Options:

    • Gzip compression - requires a library like pako, may be expensive
    • Cap'n proto packing: https://capnproto.org/encoding.html
    • Protobuf varints: https://developers.google.com/protocol-buffers/docs/encoding

    Use cases:

    • Dense tile pyramids
    • Sparse pyramids (tippecanoe output)
    v3 
    opened by bdon 9
  • Cordova support?

    Cordova support?

    I'm using Cordova/Ionic in order to serve offline tiles. I'm doing this by leveraging sqlite-ext to open a mbtiles file on the device and serve the tiles from there. Is there a way to to use pmtiles in Cordova in similar manor? From the documentation it seems that there's a need to use memory mapped file or something similar, have you experimented with this?

    opened by HarelM 9
  • writer: Leaf directories: Find best base zoom

    writer: Leaf directories: Find best base zoom

    ... to avoid extra indirection for as many tiles as we can

    Previously, we hardcoded a "base_zoom = 7", which is only only optimal for a whole world map. instead "7" is replaced with min zoom that fits all tiles.

    I only tested on one example (Bugianen, 152742 tiles) and got the expected base zoom of 14.

    
    ```sh
    sqlite3 Bugianen.mbtiles "SELECT  zoom_level, COUNT(*) FROM tiles GROUP BY zoom_level"
    12|448
    13|1792
    14|7168
    15|28672
    16|114662
    
    PYTHONPATH=$PWD bin/pmtiles-convert Bugianen.mbtiles optim_Bugianen.pmtiles
    Num tiles: 152742
    Num unique tiles: 151947
    Num leaves: 7168
    

    So, this needs more testing.

    opened by eddy-geek 8
  • pmtiles-convert Attribute Error

    pmtiles-convert Attribute Error

    I'm getting a python AttributeError when converting a .mbtiles file to .pmtiles

    pmtiles-convert postcode.mbtiles postcode2.pmtiles
    ('compression:', 'disabled')
    Traceback (most recent call last):
      File "/home/malcolm/.local/bin/pmtiles-convert", line 38, in <module>
        mbtiles_to_pmtiles(args.input, args.output, args.maxzoom, args.gzip)
      File "/home/malcolm/.local/lib/python2.7/site-packages/pmtiles/convert.py", line 40, in mbtiles_to_pmtiles
        writer.write_tile(row[0], row[1], flipped, force_compress(row[3], gzip))
      File "/home/malcolm/.local/lib/python2.7/site-packages/pmtiles/convert.py", line 15, in force_compress
        return gzip.decompress(data)
    AttributeError: 'module' object has no attribute 'decompress'
    

    postcode.zip

    opened by mem48 7
  • Consumes all memory on large input

    Consumes all memory on large input

    I'm trying to convert a 66 GB file and it quickly consumes 32GB ram then stops.

    Is there a solution to converting large files besides launching a super huge VM to handle conversions?

    opened by j 7
  • Unable to display map on browsers

    Unable to display map on browsers

    Hi! I'm new to this project. I tried running some html files in the example section in Safari/Chrome but maps were not shown. I got the following errors: image I couldn't figure out why fetch is aborted. Is there something I'm missing here?

    Thank you.

    opened by xinyuluo 7
  • Split a pmtiles file

    Split a pmtiles file

    Some hosts (like github pages) have maximum file sizes. Alternatives like https://github.com/phiresky/sql.js-httpvfs provide a way to split the tile archive until it is less than that max file size (https://github.com/phiresky/sql.js-httpvfs/blob/master/create_db.sh). Would it be possible for the pmtiles reader and writer to optionally support splitting a pmtiles file?

    opened by msbarry 6
  • canvas tile display seems to be transparent :/

    canvas tile display seems to be transparent :/

    hi, i'm using our own pmtiles tileset server, the test url is : https://tilesets.urbanease.io/cadastre/64/64102/without_protobuf.pmtiles the location for seeing it is :bayonne, france latlng=[43.492949,-1.474841]

    on the viewer, all seems to be ok bit leaflet preview don't work viewer i'm using react and leaflet with the npm protomaps package version 1.19.0

    my code is simple const map = useMap(); const url = 'https://tilesets.urbanease.io/cadastre/64/64102/without_protobuf.pmtiles'; const layer = protomaps.leafletLayer({ url: url, id: 'cadastral', }); layer.addTo(map);

    canvas are created but seems to be transparent, colors in paint_rules layer are good and opacity ok

    i don't understand where is the pb bad pmtiles file? no compatibility with leaflet? thx for help

    opened by DavidDvpt 5
  • More detailed Specification

    More detailed Specification

    Hey :)

    First of all. Thank you for the great format. It is imho the perfect solution to a problem that will become more and more prevalent in the near future.

    I tried to implement my own reader / writer in rust and found myself looking at the first-party implementations quite a lot, because I stumbled upon things that are not really clear in the specification.

    I think the project would benefit a lot from having a WAY MORE detailed specification (at least more than something I could print on a single page) and I was wondering whether a contribution on my part would be welcomed.

    I took the opportunity and wrote a really rough draft, of the section on the header. Just to give you an impression of what I would envision and get your feedback.

    PS: It's also totally fine if you do not think the specification needs to be improved.

    opened by DerZade 1
  • Refactor JS client to use streams instead of ArrayBuffers

    Refactor JS client to use streams instead of ArrayBuffers

    This will require a major version bump, as the Source API should return a ReadableStream. This is made possible by Lambda now supporting Node 18.

    Should also include #90 API changes as well to use If-Match.

    • [ ] fflate readablestream
    • [ ] varint readable stream
    opened by bdon 1
  • ETag problems in JavaScript client + passing through other metadata

    ETag problems in JavaScript client + passing through other metadata

    If the new resource has a new ETag but it shorter than the previous, the server might return 416 Range not Satisfiable, which does not have an accompanying ETag. This will invalidate the header, but present a bunch of errors in the console.

    We should unify on using the If-Match header in sending the requests, which will return 412 Precondition Failed in the mismatch case, which is designed for this specific situation.

    bug 
    opened by bdon 0
  • Inspector app improvements

    Inspector app improvements

    • [x] SVG tile previews should be zoomable
    • [x] Should be able to drill down into leaf directories
    • [x] should be able to preview vector tiles in leaflet
    • [ ] SVG should be feature-level inspectable
    • [ ] map preview should be feature-level inspectable
    • [ ] see directory Len and header-level metadata
    • [ ] inspect SVG with mismatched extents
    • [ ] correctly read tile and map hash states
    opened by bdon 1
Releases(v0.0.0-alpha)
Automatically Forward files from groups to channel & FSub

Backup & ForceSub Automatically Forward files from groups to channel & Do force sub on members Variables API_ID : Get from my.telegram.org API_HASH :

Arunkumar Shibu 7 Nov 06, 2022
😈 Discord RAGE is a Python tool that allows you to automatically spam messages in Discord

😈 Discord RAGE Python tool that allows you to automatically spam messages in Discord 🏹 Setup Make sure you have Python installed and PIP is added to

Alphalius 4 Jun 12, 2022
Build better AWS infrastructure

Sceptre About Sceptre is a tool to drive AWS CloudFormation. It automates the mundane, repetitive and error-prone tasks, enabling you to concentrate o

sceptre 1.4k Jan 04, 2023
Sail is a free CLI tool to deploy, manage and scale WordPress applications in the DigitalOcean cloud.

Deploy WordPress to DigitalOcean with Sail Sail is a free CLI tool to deploy, manage and scale WordPress applications in the DigitalOcean cloud. Conte

Konstantin Kovshenin 159 Dec 12, 2022
Telegram üzerinden paylaşılan kısa linkleri geçmenin daha hızlı bir yolu

Telegram Url skipper Telegramda paylaşılan kısa linkleri geçmenin daha hızlı bir yolu · Hata Raporla · Öneri Yap İçerik Tablosu Kurulum Kullanım Lisan

WarForPeace 6 Oct 07, 2022
A telegram bot to interact with a Minecraft Server

telegram-mc-bot A telegram bot to interact with a Minecraft Server It has the following commands: /status - Returns the server status (Online/Offline)

KleynArt 1 Dec 09, 2021
MVP monorepo to rapidly develop scalable, reliable, high-quality components for Amazon Linux instance configuration management

Ansible Amazon Base Repository Ansible Amazon Base Repository About Setting Up Ansible Environment Configuring Python VENV and Ansible Editor Configur

Artem Veremey 1 Aug 06, 2022
One of the best Telegram renamer bot with many new features

Renamer-Bot I think this repo gonna become one of the best renamer open source 🥰 . Please Give a ⭐ if you like this repo and also try following me fo

Ns Bots 97 Jan 06, 2023
A command line interface for accessing google drive

Drive Cli Get the ability to access Google Drive without leaving your terminal. Inspiration Google Drive has become a vital part of our day to day lif

Chirag Shetty 538 Dec 12, 2022
Opasium AI was specifically designed for the Opasium Games discord only. It is a bot that covers the basic functions of any other bot.

OpasiumAI Opasium AI was specifically designed for the Opasium Games discord only. It is a bot that covers the basic functions of any other bot. Insta

Dan 3 Oct 15, 2021
A powerful Lavalink library for Discord.py.

A robust and powerful Lavalink wrapper for Discord.py! Documentation Official Documentation. Support For support using WaveLink, please join the offic

Pythonista 254 Dec 29, 2022
A Telegram bot for combining emojis.

combimoji combimoji is a Telegram bot for combining emojis. How can I use it? You can find combimoji at @combimoji_bot, however it is not up (as of No

Yarema Mishchenko 2 Dec 02, 2021
light wrapper for indeed.com api

Simple wrapper for indeed api. go to indeed.com - register for api publisher token example from indeed import IndeedApi token = 'your token' api =

16 Sep 21, 2022
A Phyton script working for stream twits from twitter by tweepy to mongoDB

twitter-to-mongo A python script that uses the Tweepy library to pull Tweets with specific keywords from Twitter's Streaming API, and then stores the

3 Feb 03, 2022
Python library for using SMS.ir web services

smsir smsir is a Python library for using SMS web services www.sms.ir Installation Use the package manager pip to install smsir. pip install smsir Usa

mohammad reza 2 Oct 14, 2022
OAN Music - Highly advanced User Music Bot

ཧᜰ꙰ꦿ➢𝐎𝐀𝐍༒☛ 🎧 Advanced 𝐎𝐀𝐍 Music bot. 🔗 𝐏𝐨𝐰𝐞𝐫𝐞𝐝 𝐛𝐲 : ➢𝐀ttitude

Attitude king 5 Feb 25, 2022
PancakeTrade - Limit orders and more for PancakeSwap on Binance Smart Chain

PancakeTrade helps you create limit orders and more for your BEP-20 tokens that swap against BNB on PancakeSwap. The bot is controlled by Telegram so you can interact from anywhere.

Valentin Bersier 187 Dec 20, 2022
To send an Instagram message using Python

To send an Instagram message using Python, you must have an Instagram account and install the Instabot library in your Python virtual environment.

Coding Taggers 1 Dec 18, 2021
A module to get data about anime characters, news, info, lyrics and more.

Animec A module to get data about anime characters, news, info, lyrics and more. The module scrapes myanimelist to parse requested data. If you wish t

DriftAsimov 31 Aug 31, 2022
Simple integrate of API musixmatch.com with python

Python Musixmatch Simple integrate of API musixmatch.com with python Quick start $ pip install pymusixmatch or $ python setup.py install Authenticatio

Hudson Brendon 79 Dec 20, 2022