Skip to content

Instantly share code, notes, and snippets.

@mappingvermont
Created May 26, 2016 22:00
Show Gist options
  • Save mappingvermont/1422f3b8ed56934fb2d02a9f93901e2b to your computer and use it in GitHub Desktop.
Save mappingvermont/1422f3b8ed56934fb2d02a9f93901e2b 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>
<!-- slider library-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/8.2.1/nouislider.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/8.2.1/nouislider.min.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>
<div id="info-pane" class="leaflet-bar">
<div id="slider"></div>
<br>
<label id="min">
0 meters
</label><br>
<label id="max">
4000 meters
</label>
<hr>
<div id="pixel-value"></div>
</div>
<div id='photodiv'>
<img id="photo"/>
</div>
<script>
// create a UI slider for the end user to toggle the pixel range to display
var slider = document.getElementById('slider');
noUiSlider.create(slider, {
start: [0, 4000],
step: 100,
connect: true,
range: {
'min': 0,
'max': 8000
}
});
// When the slider value changes, update the input and span
slider.noUiSlider.on('set', function (values, handle) {
document.getElementById('min').innerHTML = parseInt(values[0], 10) + ' meters';
document.getElementById('max').innerHTML = parseInt(values[1], 10) + ' meters';
// redraw the tiles without resetting
for (t in lerc._tiles)
lerc._redrawTile(lerc._tiles[t]);
});
var southWest = L.latLng(-90, -179),
northEast = L.latLng(90, 179),
worldBounds = L.latLngBounds(southWest, northEast);
var map = L.map('map', {
noWrap: true,
minZoom: 3,
maxBounds: worldBounds
}).setView([43.684639, -79.384956], 15);
var toronto = L.tileLayer.canvas({
noWrap: true,
attribution: 'USGS, Esri'
});
toronto.drawTile = function (canvas, tilePoint, zoom) {
drawData = function (img, ctx) {
ctx.drawImage(img, 0, 0);
//console.log(img);
var width = img.width;
var height = img.height;
var min = slider.noUiSlider.get()[0];
var max = slider.noUiSlider.get()[1];
var imageData = ctx.getImageData(0, 0, width, height);
var data = imageData.data;
// Invert image
data = invert(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://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/' + zoom + '/' + tilePoint.y + '/' + tilePoint.x;
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
}
}
};
map.on('mousemove', function (e) {
// the x/y of the tile url
var layerPoint = map.project(e.latlng).floor();
var tilePoint = layerPoint.divideBy(256).floor();
var block = toronto._tiles[tilePoint.x + ':' + tilePoint.y].img;
var layerPoint_px = e.layerPoint
// Read the data value from the block if it exists
if (block) {
// No idea how this black magic works, but it does
var pointInTile = layerPoint.subtract(tilePoint.multiplyBy(256));
// read in the image
var canvas = document.createElement('canvas');
canvas.width = block.width;
canvas.height = block.height;
canvas.getContext('2d').drawImage(block, 0, 0, block.width, block.height);
// Get the rgba color, using the inversion
var rgba = invert(canvas.getContext('2d').getImageData(pointInTile.x, pointInTile.y, 1, 1).data);
var rgba_txt = 'rgba(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ',' + rgba[3] + ')';
// Color the info pane to match
var info = document.getElementById('info-pane');
info.style.background = rgba_txt;
} else {
document.getElementById('pixel-value').innerHTML = "Elevation: undefined";
}
})
var invert = function(data) {
for (var i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i]; // red
data[i + 1] = 255 - data[i + 1]; // green
data[i + 2] = 255 - data[i + 2]; // blue
}
return data
};
var decode_date = function(rgba) {
var julian_day = rgba[0] + rgba[1]
var band3_str = rgba[2].toString();
var confidence = parseInt(band3_str[0])
var year = parseInt(band3_str.slice(1)) + 2000
//http://stackoverflow.com/questions/4048688
var date = new Date(year, 0);
var final_date = new Date(date.setDate(julian_day));
return [date, confidence]
};
toronto.addTo(map);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment