Skip to content

Instantly share code, notes, and snippets.

@mappingvermont
Last active February 10, 2017 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mappingvermont/ae73071d8569aee94e23134a7b3e1c04 to your computer and use it in GitHub Desktop.
Save mappingvermont/ae73071d8569aee94e23134a7b3e1c04 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Filtering Pixels in Leaflet</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<!-- Load Leaflet from CDN-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/leaflet/0.7.7/leaflet.css" />
<script src="https://cdn.jsdelivr.net/leaflet/0.7.7/leaflet.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
#info-pane {
position: absolute;
top: 10px;
right: 10px;
min-width: 200px;
z-index: 10;
padding: 1em;
background: white;
}
.noUi-connect {
background: #CCC;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map = L.map('map', {
noWrap: true,
minZoom: 3,
maxZoom: 16,
}).setView([-0, 0], 3);
var Stamen_TonerLite = L.tileLayer('http://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.{ext}', {
attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> &mdash; Map data &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
subdomains: 'abcd',
minZoom: 0,
maxZoom: 20,
ext: 'png'
});
var start_2016 =
map.addLayer(Stamen_TonerLite);
var glad = L.tileLayer.canvas({
noWrap: true,
attribution: 'USGS, Esri',
});
glad.drawTile = function(canvas, tilePoint, zoom) {
drawData = function(img, ctx) {
ctx.drawImage(img, 0, 0);
var width = img.width;
var height = img.height;
var imageData = ctx.getImageData(0, 0, width, height);
var data = imageData.data;
// Filter image
data = filter(data)
ctx.putImageData(imageData, 0, 0);
}
var tileIndex = tilePoint.x + ':' + tilePoint.y;
var tile = this._tiles[tileIndex];
var xhr = new XMLHttpRequest();
xhr.responseType = "arraybuffer";
var url = 'http://wri-tiles.s3.amazonaws.com/glad_prod/tiles/' + zoom + '/' + tilePoint.x + '/' + tilePoint.y + '.png';
xhr.open("Get", url, true);
xhr.send();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var arrayBufferView = new Uint8Array(xhr.response);
var blob = new Blob([arrayBufferView], {
type: "image/jpeg"
});
var imageUrl = URL.createObjectURL(blob);
var img = new Image();
img.onload = function() {
tile.img = img
drawData(tile.img, canvas.getContext('2d'));
}
img.src = imageUrl
}
}
};
var decode_data = function(rgba) {
// find the total days of the pixel by
// multiplying the red band by 255 and adding
// the green band to that
var total_days = rgba[0] * 255 + rgba[1];
// take the total days value and divide by 365 to
// get the year_offset. Add 15 to this (i.e 0 + 15 = 2015)
// or 1 + 15 = 2016
var year_int = parseInt(total_days / 365) + 15;
// Multiply by 1000 to give us year in YYDDD format
// (i.e. 15000 or 16000)
var year = parseInt(year_int * 1000)
// Find the remaining days to get the julian day for
// that year
var julian_day = total_days % 365;
// Add to get YYDDD date val
var date_val = year + julian_day;
// Convert the blue band to string, leading
// zeros if it's not currently three digits
// this occurs very rarely; where there's an intensity
// value but no date/confidence for it. Due to bilinear
// resampling
var band3_str = pad(rgba[2].toString());
// Grab confidence (the first value) from this string
// confidence is stored as 1/2, subtract one to make it 0/1
var confidence = parseInt(band3_str[0]) - 1
// Grab the raw intensity value from the pixel; ranges from 1 - 55
var intensity_raw = parseInt(band3_str.slice(1, 3))
// Scale the intensity to make it visible
var intensity = intensity_raw * 50
// Set intensity to 255 if it's > than that value
if (intensity > 255) {
intensity = 255
}
return {year_int: year_int, intensity: intensity}
};
var pad = function(num) {
var s = "00" + num;
return s.substr(s.length - 3);
}
var filter = function(data) {
for (var i = 0; i < data.length; i += 4) {
pixelInfo = decode_data(data.slice(i, i + 4))
//console.log(pixelInfo)
switch (pixelInfo.year_int) {
// if the data is from 2015, color it green
case 15:
data[i] = 107,
data[i + 1] = 244,
data[i + 2] = 66
break;
// if it's from 2016, call it pink
case 16:
data[i] = 220,
data[i + 1] = 102,
data[i + 2] = 153
break;
// if it's 2017, color it yellow
case 17:
data[i] = 252,
data[i + 1] = 252,
data[i + 2] = 15
break;
}
// regardless, display the proper intensity
data[i + 3] = pixelInfo.intensity
}
return data
};
map.addLayer(glad)
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment