Create a Dynamic Tiler
rio-tiler
aims to be a lightweight plugin for rasterio
to read slippy map
tiles from a raster sources.
Given that rio-tiler
allows for simple, efficient reading of tiles, you can
then leverage rio-tiler
to create a dynamic tile server to display raster
tiles on a web map.
There are couple tile servers built on top of rio-tiler:
Example Application¶
To build a simple dynamic tiling application, we can use
FastAPI. Note that titiler
uses
FastAPI
internally, so you might consider using titiler
instead of making
your own API.
Requirements¶
rio-tiler ~= 4.0
fastapi
uvicorn
Install with
pip install fastapi uvicorn rio-tiler
app.py
¶
"""rio-tiler tile server."""
import os
from fastapi import FastAPI, Query
from starlette.requests import Request
from starlette.responses import Response
from rio_tiler.profiles import img_profiles
from rio_tiler.io import Reader
app = FastAPI(
title="rio-tiler",
description="A lightweight Cloud Optimized GeoTIFF tile server",
)
@app.get(
r"/{z}/{x}/{y}.png",
responses={
200: {
"content": {"image/png": {}}, "description": "Return an image.",
}
},
response_class=Response,
description="Read COG and return a tile",
)
def tile(
z: int,
x: int,
y: int,
url: str = Query(..., description="Cloud Optimized GeoTIFF URL."),
):
"""Handle tile requests."""
with Reader(url) as cog:
img = cog.tile(x, y, z)
content = img.render(img_format="PNG", **img_profiles.get("png"))
return Response(content, media_type="image/png")
@app.get("/tilejson.json", responses={200: {"description": "Return a tilejson"}})
def tilejson(
request: Request,
url: str = Query(..., description="Cloud Optimized GeoTIFF URL."),
):
"""Return TileJSON document for a COG."""
tile_url = str(request.url_for("tile", z="{z}", x="{x}", y="{y}"))
tile_url = f"{tile_url}?url={url}"
with Reader(url) as cog:
return {
"bounds": cog.get_geographic_bounds(cog.tms.rasterio_geographic_crs),
"minzoom": cog.minzoom,
"maxzoom": cog.maxzoom,
"name": os.path.basename(url),
"tiles": [tile_url],
}
Launch Example¶
Use uvicorn
to launch the application. Note that app:app
tells uvicorn
to
call the app
function within app.py
, so you must be in the same directory as
app.py
.
uvicorn app:app --reload