Skip to content

Instantly share code, notes, and snippets.

@frogcat
Created September 8, 2020 12:02
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 frogcat/b4172e63310e15e25681cd84994599b8 to your computer and use it in GitHub Desktop.
Save frogcat/b4172e63310e15e25681cd84994599b8 to your computer and use it in GitHub Desktop.

petaviron : click save button to download transformed image

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>petaviron</title>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" />
<script src="https://unpkg.com/jszip@3.1.5/dist/jszip.min.js"></script>
<script src="https://unpkg.com/file-saver@1.3.8/FileSaver.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet-hash@0.2.1/leaflet-hash.js"></script>
<script src="https://frogcat.github.io/leaflet-imageoverlay-gcp/dist/leaflet-imageoverlay-gcp.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/exif-js"></script>
<style>
button {
cursor: pointer;
}
#map {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#control {
position: absolute;
bottom: 10px;
left: 10px;
width: 140px;
height: auto;
border-radius: 10px;
padding: 10px;
background: rgba(0, 0, 0, 0.75);
z-index: 1000;
}
#opacityText {
width: 100%;
font-size: 10pt;
color: white;
display: block;
margin: 0;
padding: 0;
text-align: center;
font-family: Consolas;
font-size: 14pt;
}
#opacity {
width: 100%;
display: block;
margin: 0;
padding: 0;
}
.instruction {
text-align: center;
}
.gr {
font-size: 14pt;
font-family: Consolas;
}
button.gr {
background: black;
color: white;
border-radius: 10px;
border: none;
padding: 10px;
}
button.gr:hover {
background: orange;
}
#save {
font-family: Consolas;
font-size: 14pt;
display: block;
width: 100%;
background: white;
color: black;
margin: 7px 0;
border: none;
border-radius: 10px;
}
#save:hover {
background: orange;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="control" style="display:none;">
<label for="opacity" id="opacityText">opacity 75%</label>
<input type="range" id="opacity" min="0" max="1" step="0.01" value="0.75" />
<button id="save">save</button>
</div>
<script src="script.js"></script>
</body>
</html>
var map = L.map("map", L.extend({
maxZoom: 20,
center: [35.61748, 139.62071],
zoom: 14
}, L.Hash.parseHash(location.hash)));
map.zoomControl.setPosition("bottomright");
map.attributionControl.setPrefix("<a href='https://github.com/frogcat/petaviron'>petaviron</a>");
L.hash(map);
L.control.layers({
"GSI photo": L.tileLayer("https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg", {
attribution: "<a href='http://maps.gsi.go.jp/development/ichiran.html'>GSI</a>",
maxNativeZoom: 18,
maxZoom: 20
}).addTo(map),
"GSI pale": L.tileLayer("https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png", {
attribution: "<a href='http://maps.gsi.go.jp/development/ichiran.html'>GSI</a>",
maxNativeZoom: 18,
maxZoom: 20
}),
"GSI std": L.tileLayer("https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png", {
attribution: "<a href='http://maps.gsi.go.jp/development/ichiran.html'>GSI</a>",
maxNativeZoom: 18,
maxZoom: 20
}),
"OpenStreetMap": L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "&copy; <a href='http://osm.org/copyright'>OpenStreetMap</a> contributors",
maxNativeZoom: 18,
maxZoom: 20
})
}).addTo(map);
var popup = L.popup({
closeButton: false,
autoClose: false,
closeOnEscapeKey: false,
closeOnClick: false,
className: "instruction"
});
popup.setLatLng(map.getCenter());
popup.setContent("<button id='start' class='gr'>Click me to overlay your image</button>");
popup.openOn(map);
map.on("moveend", function() {
popup.setLatLng(map.getCenter());
});
$("#start").on("click", function() {
$("<input type='file' accept='image/*'/>").change(function() {
var file = Array.apply(null, this.files).find(function(f) {
return f.type.indexOf("image/") === 0;
});
if (!file) return;
EXIF.getData(file, function() {
var data = EXIF.getAllTags(file);
if (data["GPSLatitude"] && data["GPSLongitude"]) {
var ll = [
data["GPSLatitude"],
data["GPSLongitude"]
].map(a => a[0] + a[1] / 60 + a[2] / 3600);
if (data["GPSLatitudeRef"] !== "N") ll[0] *= -1;
if (data["GPSLongitudeRef"] !== "E") ll[1] *= -1;
if (confirm("EXIF GPSLatitude/GPSLongitude found.\n [OK] Set the map view to EXIF location \n [Cancel] Don't change the map view"))
map.panTo(ll, {
animate: false
});
}
var image = new Image();
image.title = file.name;
image.crossOrigin = "anonymous";
image.onload = function() {
window.URL.revokeObjectURL(image.src);
init(image);
};
image.src = window.URL.createObjectURL(file);
});
}).click();
});
function init(img) {
map.closePopup();
$("#control").fadeIn();
var initialControlPoints = (function() {
var size = map.getSize();
var src = L.point(img.naturalWidth, img.naturalHeight);
var dst = src.multiplyBy(Math.min(size.x / src.x * 0.8, size.y / src.y * 0.8, 1));
var c = size.divideBy(2);
var d = dst.divideBy(2);
return [{
imagePoint: L.point(0, 0),
latlng: map.containerPointToLatLng(L.point(c.x - d.x, c.y - d.y))
}, {
imagePoint: L.point(src.x, 0),
latlng: map.containerPointToLatLng(L.point(c.x + d.x, c.y - d.y))
}, {
imagePoint: L.point(src.x, src.y),
latlng: map.containerPointToLatLng(L.point(c.x + d.x, c.y + d.y))
}, {
imagePoint: L.point(0, src.y),
latlng: map.containerPointToLatLng(L.point(c.x - d.x, c.y + d.y))
}];
})();
var markerGroup = L.featureGroup([]).addTo(map);
var overlay = L.imageOverlay.gcp(img, initialControlPoints, {
opacity: $("#opacity").val()
}).addTo(map);
overlay.on("click", function(e) {
var p = overlay.containerPointToImagePoint(e.containerPoint);
if (p === null) return;
var button = document.createElement("button");
button.setAttribute("class", "gr");
button.appendChild(document.createTextNode("Click to remove"));
var me = L.marker(e.latlng, {
draggable: true,
imagePoint: p
}).bindPopup(button).addTo(markerGroup);
button.addEventListener("click", function() {
markerGroup.removeLayer(me);
});
});
markerGroup.on("layeradd layerremove change", function(e) {
if (e.type === "layeradd") {
e.layer.on("drag", function() {
markerGroup.fire("change");
});
}
var markers = markerGroup.getLayers();
if (markers.length < 3) return;
overlay.setGroundControlPoints(markers.map(marker => {
return {
latlng: marker.getLatLng(),
imagePoint: marker.options.imagePoint
};
}));
}).addTo(map);
map.on("resize zoom viewreset moveend", function() {
markerGroup.fire("change");
});
initialControlPoints.forEach(a => {
L.marker(a.latlng, {
draggable: true,
imagePoint: a.imagePoint
}).bindPopup("<span class='gr'>drag me</span>").addTo(markerGroup).openPopup();
});
$("#opacity").on("input", function() {
overlay.setOpacity($(this).val());
$("#opacityText").text("opacity " + Math.floor(($(this).val() * 100)) + "%");
}).trigger("input");
$("#save").on("click", function() {
if (overlay._canvas) {
overlay._canvas.toBlob(function(blob) {
saveAs(blob, "petaviron" + (new Date().getTime()) + ".png");
});
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment