"""rio-tiler dynamic tile server for I7D16.tif""" import os from pathlib import Path from fastapi import FastAPI, HTTPException from fastapi.responses import HTMLResponse from starlette.requests import Request from starlette.responses import Response from rio_tiler.errors import TileOutsideBounds from rio_tiler.io import Reader from rio_tiler.profiles import img_profiles DATA_PATH = str(Path(__file__).parent / "data" / "I7D16.tif") # Per-band rescale range derived from p2/p98 statistics of the source image # Band order: Red, Green, Blue (band 4 NIR is ignored) RESCALE = [ (6130, 40453), # Red (10641, 41211), # Green (12482, 36323), # Blue ] app = FastAPI( title="rio-tiler", description="Dynamic tile server for I7D16.tif (NJ 2020 aerial imagery)", ) @app.get( "/tiles/{z}/{x}/{y}.png", responses={ 200: {"content": {"image/png": {}}, "description": "Return a PNG tile."}, 404: {"description": "Tile outside image bounds."}, }, response_class=Response, description="Read COG tile and return a PNG image (RGB bands, UInt16 rescaled)", ) def tile(z: int, x: int, y: int): """Return a map tile for the given z/x/y coordinates.""" try: with Reader(DATA_PATH) as cog: img = cog.tile(x, y, z, indexes=(1, 2, 3)) except TileOutsideBounds: raise HTTPException(status_code=404, detail="Tile outside image bounds") content = img.render( img_format="PNG", rescale=RESCALE, **img_profiles.get("png", {}), ) return Response(content, media_type="image/png") @app.get("/tilejson.json", responses={200: {"description": "Return a TileJSON document"}}) def tilejson(request: Request): """Return a TileJSON 2.2.0 document describing the available tiles.""" with Reader(DATA_PATH) as cog: bounds = cog.get_geographic_bounds(cog.tms.rasterio_geographic_crs) minzoom = cog.minzoom maxzoom = cog.maxzoom base_url = str(request.base_url).rstrip("/") tile_url = f"{base_url}/tiles/{{z}}/{{x}}/{{y}}.png" return { "tilejson": "2.2.0", "name": os.path.basename(DATA_PATH), "description": "NJ Open Imagery 2020 - NAD83(2011) / New Jersey (ftUS)", "tiles": [tile_url], "bounds": list(bounds), "minzoom": minzoom, "maxzoom": maxzoom, "center": [ (bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2, minzoom + 2, ], } @app.get("/", response_class=HTMLResponse) def index(request: Request): """Simple Leaflet.js viewer for the imagery.""" with Reader(DATA_PATH) as cog: bounds = cog.get_geographic_bounds(cog.tms.rasterio_geographic_crs) minzoom = cog.minzoom maxzoom = cog.maxzoom base_url = str(request.base_url).rstrip("/") tile_url = f"{base_url}/tiles/{{z}}/{{x}}/{{y}}.png" center_lat = (bounds[1] + bounds[3]) / 2 center_lng = (bounds[0] + bounds[2]) / 2 init_zoom = minzoom + 2 return f""" I7D16 Tile Viewer
I7D16.tif
NJ Open Imagery 2020
Zoom: {minzoom}–{maxzoom}
CRS: NAD83(2011) / NJ ftUS
"""