Building a Dynamic Tile Server Using Cloud Optimized GeoTIFF(COG) with TiTiler
Tags: foss4g, qgis, titiler, cog
Published: 2023-12-21 12:20:14

![img](https://memo.dayjournal.dev/images/try-107_00.png)

### I built a dynamic tile server using Cloud Optimized GeoTIFF (COG) with TiTiler!

[TiTiler](https://devseed.com/titiler) is a dynamic tile server built on [FastAPI](https://fastapi.tiangolo.com) and [Rasterio](https://rasterio.readthedocs.io)/[GDAL](https://gdal.org). Its main features include support for [Cloud Optimized GeoTIFF(COG)](https://www.cogeo.org), multiple projection methods, various output formats (JPEG, JP2, PNG, WEBP, GTIFF, NumpyTile), WMTS, and virtual mosaic. It also provides Lambda and ECS deployment environments using AWS CDK.

## Advance Preparation

The sample data used this time is in Cloud Optimized GeoTIFF (COG) format, which can be obtained from the [Registry of Open Data on AWS](https://registry.opendata.aws) provided by AWS.

![img](https://memo.dayjournal.dev/images/try-107_02.png)

I selected the COG of "Sentinel-2".
[https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/54/T/WN/2023/8/S2A_54TWN_20230815_0_L2A/TCI.tif](https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/54/T/WN/2023/8/S2A_54TWN_20230815_0_L2A/TCI.tif)

![img](https://memo.dayjournal.dev/images/try-107_03.png)

## Install & launch TiTiler

Install TiTiler. This time, we will use Docker to start it locally.  

Clone the TiTiler repository.

```sh
git clone https://github.com/developmentseed/titiler.git
cd titiler
```

Start TiTiler.

```sh
docker-compose up --build titiler
```

![img](https://memo.dayjournal.dev/images/try-107_04.png)

After launching, go to "http://localhost:8000". The TiTiler top page will appear.
![img](https://memo.dayjournal.dev/images/try-107_05.png)

You can check the actual usage by looking at the API documentation.
![img](https://memo.dayjournal.dev/images/try-107_06.png)

## Obtaining basic data information

First, basic data information is acquired.  

Select "/cog/info" → enter COG URL in Dataset URL → click "Execute."
![img](https://memo.dayjournal.dev/images/try-107_10.png)

Basic information on the target data can be obtained in JSON.

```json
{
  "bounds": [
    140.99975320947394,
    42.356322389620374,
    142.3544473299751,
    43.35285539188815
  ],
  "minzoom": 7,
  "maxzoom": 13,
  "band_metadata": [
    [
      "b1",
      {}
    ],
    [
      "b2",
      {}
    ],
    [
      "b3",
      {}
    ]
  ],
  "band_descriptions": [
    [
      "b1",
      ""
    ],
    [
      "b2",
      ""
    ],
    [
      "b3",
      ""
    ]
  ],
  "dtype": "uint8",
  "nodata_type": "Nodata",
  "colorinterp": [
    "red",
    "green",
    "blue"
  ],
  "driver": "GTiff",
  "count": 3,
  "width": 10980,
  "height": 10980,
  "overviews": [
    2,
    4,
    8,
    16
  ],
  "nodata_value": 0
}
```

## Displaying data in a viewer

Next, display the target data in the default viewer provided by TiTiler!

Select the "/cog/viewer" entry. Then, by accessing "http://localhost:8000/cog/viewer" directly, the viewer screen will appear.
![img](https://memo.dayjournal.dev/images/try-107_07.png)

Access the viewer → Input COG URL → Click "Apply."
![img](https://memo.dayjournal.dev/images/try-107_08.png)

The target data is displayed on the viewer. You can also try zooming in/out and setting parameters.
![img](https://memo.dayjournal.dev/images/try-107_09.png)

## Obtaining basic information in GeoJSON format

Next, get basic information in GeoJSON format and display it in QGIS. 

Use the API of "/cog/info.geojson" to read GeoJSON format data in QGIS.

```url
http://localhost:8000/cog/info.geojson?url=https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/54/T/WN/2023/8/S2A_54TWN_20230815_0_L2A/TCI.tif
```

![img](https://memo.dayjournal.dev/images/try-107_11.png)

You can see the range polygons of the target data and the basic information in the attributes.
![img](https://memo.dayjournal.dev/images/try-107_12.png)

## Obtaining XYZ Tiles

Next, get the raster tiles in XYZ Tiles format and display them in QGIS.

Use the API "/cog/tiles" and read XYZ Tiles raster tiles in QGIS.

```url
http://localhost:8000/cog/tiles/WebMercatorQuad/{z}/{x}/{y}.png?url=https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/54/T/WN/2023/8/S2A_54TWN_20230815_0_L2A/TCI.tif
```

![img](https://memo.dayjournal.dev/images/try-107_13.png)

You can see that the target data is dynamically delivered in XYZ Tiles.
![img](https://memo.dayjournal.dev/images/try-107_14.png)

## Obtaining WMTS

Finally, get the raster tiles in WMTS format and display them in QGIS.

Use the API in "/cog/WMTSCapabilities.xml" to load WMTS raster tiles in QGIS.

```url
http://localhost:8000/cog/WMTSCapabilities.xml?url=https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/54/T/WN/2023/8/S2A_54TWN_20230815_0_L2A/TCI.tif
```

![img](https://memo.dayjournal.dev/images/try-107_15.png)

You can see that the target data is dynamically delivered in WMTS.
![img](https://memo.dayjournal.dev/images/try-107_16.png)

<br>

The TiTiler can easily deliver dynamic tile in various formats by specifying the data URL! Static tile delivery is suitable for simple raster tile delivery, but dynamic tile delivery is also a choice when various formats or special processing is required.

TiTiler comes standard with a built-in viewer for immediate data visualization. In addition, a deployment environment to Lambda and ECS is available using AWS CDK, and detailed documentation is provided.

There are many other features that were unable to introduce in this article, so please try them out for yourself!

<br>

Related Articles

{% link https://dev.to/mierune/comtiles-cloud-optimized-map-tiles-hosted-on-amazon-s3-and-visualized-with-maplibre-gl-js-3bed %}

{% link https://dev.to/mierune/trying-out-various-qgis-processing-2ej1 %}

{% link https://dev.to/mierune/trying-out-various-turfjs-547k %}

<br>

References
[TiTiler](https://devseed.com/titiler/)
[QGIS](http://www.qgis.org/ja/site/)