Visualizing GeoTIFF Tiles with OpenLayers

This blog is about visualizing raster data like elevation models or multiband satellite products as Web maps. It builds upon concepts developed at EOX IT Services GmbH and presented in an earlier post. Unlike using just single source data files the new concept extends to the handling of tiled TIFF pyramids (like a regular WMTS service does it with PNG or JPG), making it possible to display the data content in an appropriate resolution for each requested zoom level and area of interest.

Over the past weeks I worked on prototyping an OpenLayers webmap functionality for which processing is done on the client and not on the server side. This blogpost shows the basic principles of how the prototype works and which steps I took until getting to the final result. This forms the core of the master thesis which I have been presenting at the GIS Department of University of Salzburg, Austria.

The result

Example 1: An elevation model.

You can drag the sliders below to adjust the upper and lower limit of the color scale. And you can change the color scale by picking another palette from the selectbox.

The important part of the code is very simple (see the long explanation at the end of this post):

Example 2: Visualisation of NDVI calculated from Sentinel-2 satellite data.

Note that the presented overlay is a calculation of 4 bands (red, green, blue, near infrared) that are sent to the client and also processed on the client! The code snippet is as follows:

Just change the selectbox from NDVI to NDI45 in the example below and it will change the resulting image on the fly without requesting anything from the server.

This time it’s almost as simple as before. We have 5 more lines of code that define the returned calculated value based on multiple bands in the source data and sets the “noDataValue” to a value outside of the domain range (10).

That’s it! In the next part we will cover what is going on behind the scenes and which components we used to achieve these results.


The goal


The goal of this prototype was to be able to display scientific raster data like elevation models or multiband satellite data on an OpenLayers webmap but processing the data on client and not on the server. This post focuses on the technical implementation of the prototype. The in-depth scientific analysis of this method is part of the thesis and only partly covered here.

Basic Setup Principle

For the prototype we need the following components:


Browser/Website: The visualisation and – that’s the interesting part – also the processing is done completely in the browser so of course this is the part where everything is put together.

Webmap: The goal was to display the data not only in a canvas but to place it on a dynamic webmap with panning & zooming features. We implemented the prototype based on the famous OpenLayers web mapping library (v4.6.4).

Data: For the prototype my colleagues at EOX setup some sample GeoTIFF data. In the first example it is a DEM hosted on a github repository, in the second example it is satellite data from a Sentinel-2 satellite. In both cases the data is stored as pre-cached GeoTIFF tiles, so we can request them just as a regular OpenLayers WMTS source.

Parser: Since the regular WMTS service returnes regular web images (PNG) and we request GeoTIFF data we need to parse this data before we can visualize anything. This is done by the geotiff.js JavaScript library by EOX.

Plotter: The parsed GeoTIFF data is still not a human readable image since it can hold data from multiple sensors of the satellite collecting data from different (and maybe not visible) wavelengths. To make this data visible to the human eye is the job of the Plotty JavaScript library also developed by EOX.

olGeoTiff: olGeoTiff is a newly developed little javascript class that takes a WMTS layer of an OpenLayers webmap and modifies the internal tileloadFunction so that OpenLayers does not request a regular PNG image rendered by the server but downloads the original GeoTIFF data, parses it, plots it and finally places it directly onto the map as a HTML canvas element (using the high performance WebGL interface if available).

UI components: Loading “raw” GeoTIFF data to the client does only make sense if the visualisation of the data is changed on the client side several times (otherwise it might be better to process everything on the server and return the rendered image tiles ready for display). So to change the settings for our client-side plots we need some UI elements in our map. In this case we have 2 sliders (using NoUiSlider) and one select element to change the color palette.

Let’s put everything together

In this example we go through all the necessary parts needed to get the second example (NDVI over Vienna) up and running. We start with the empty HTML, add all the scripts, add our map and UI elements and finally add the code to make everything play together.

The example is basically the same as shown here in the present blogpost, but as there are a lot more scripts on this website that are not related to the prototype but necessary for the website itself I setup a clean example.


1) The basic HTML file:

2) Adding scripts & styles:

3) Adding the map und UI elements:

4) Adding the script

4.1) Setting some variables

Nothing special here – this is basically the same as the WMTS Example on the OpenLayers website:

4.2) Define our WMTS-TIFF layer

Notice the .tif file ending defined in the “url” property of the WMTS source. This shows that data is requested as GeoTIFF and not as PNG/JPG.

4.3) Define the baselayer

In this case we take the great and quite new “s2cloudless” layer from EOX (Attribution and more Info on that layer: Sentinel-2 cloudless by EOX IT Services GmbH is licensed under a Creative Commons Attribution 4.0 International License).

4.4) Map setup

4.5) Instructions for the olGeoTiff class

This is the most interesting part of the code so we go into detail here: First we create a new instance of the olGeoTiff class for the layer “wmslayer_s2”.

Thereafter we set the options for the plot:

  • We set the initial domain values to -0,2 and +0,2 (see for the plotty docs)
  • Then we set the noDataValue to “10” and the palette to “blackbody”
  • Finally we define the dataFunction – this is the part where we define how the returned value of the multiple bands gets calculated. In this example we have two functions that can be switched by the user. We take the first as default where we calculate the NDVI and return “10” when we have empty values for all bands. You can see an example of that on the lower left corner of the dataset where the background layer shines through our overlay.

That’s all there is to do to get GeoTiff support to your OpenLayers map!

4.6) Handle user input

Finally we add some listeners to our UI elements, pass their values to our olgt_s2map.plotOptions and do a redraw by invoking olgt_s2map.redraw(). Note that this part is done by using JQuery – just because I’m lazy and it’s already included in this site. JQuery is absolutely not needed for making everything work!

The final code can be found on the Demo-Website, just see the sourcecode – it is unminified by intention so that you can inspect everything easily!

Thank’s for your interest in this topic! If you have any suggestions please don’t hesitate to contact me or one of my colleagues at EOX.

During the next weeks I will analyse this method from a scientific point of few. I will compare different KPIs and find answers to some questions like when it starts making sense to switch from serverside processing to clientside processing.