Calculating NDVI and applying a custom color map.
The GeoTIFF layer in this example draws from two Sentinel 2 sources: a red band and a near infrared band. The layer style includes a color
expression that calculates the Normalized Difference Vegetation Index (NDVI) from values in the two bands. The interpolate
expression is used to map NDVI values to colors.
import 'ol/ol.css';
import GeoTIFF from 'ol/source/GeoTIFF';
import Map from 'ol/Map';
import TileLayer from 'ol/layer/WebGLTile';
const source = new GeoTIFF({
sources: [
{
// visible red, band 1 in the style expression above
url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/2020/S2A_36QWD_20200701_0_L2A/B04.tif',
max: 10000,
},
{
// near infrared, band 2 in the style expression above
url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/2020/S2A_36QWD_20200701_0_L2A/B08.tif',
max: 10000,
},
],
});
const map = new Map({
target: 'map',
layers: [
new TileLayer({
style: {
color: [
'interpolate',
['linear'],
// calculate NDVI, bands come from the sources below
[
'/',
['-', ['band', 2], ['band', 1]],
['+', ['band', 2], ['band', 1]],
],
// color ramp for NDVI values, ranging from -1 to 1
-0.2,
[191, 191, 191],
-0.1,
[219, 219, 219],
0,
[255, 255, 224],
0.025,
[255, 250, 204],
0.05,
[237, 232, 181],
0.075,
[222, 217, 156],
0.1,
[204, 199, 130],
0.125,
[189, 184, 107],
0.15,
[176, 194, 97],
0.175,
[163, 204, 89],
0.2,
[145, 191, 82],
0.25,
[128, 179, 71],
0.3,
[112, 163, 64],
0.35,
[97, 150, 54],
0.4,
[79, 138, 46],
0.45,
[64, 125, 36],
0.5,
[48, 110, 28],
0.55,
[33, 97, 18],
0.6,
[15, 84, 10],
0.65,
[0, 69, 0],
],
},
source: source,
}),
],
view: source.getView(),
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>NDVI from a Sentinel 2 COG</title>
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://unpkg.com/elm-pep"></script>
<!-- The lines below are only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,TextDecoder"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.18.3/minified.js"></script>
<style>
.map {
width: 100%;
height:400px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<script src="main.js"></script>
</body>
</html>
{
"name": "cog-math",
"dependencies": {
"ol": "6.12.0"
},
"devDependencies": {
"parcel": "^2.0.0"
},
"scripts": {
"start": "parcel index.html",
"build": "parcel build --public-url . index.html"
}
}