CINXE.COM
Wann und wo - Geotagging
<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Wann und wo - Geotagging</title> <link rel="stylesheet" href="jb.css" type="text/css"/> <style type="text/css"> html, body { min-height:100vh } #outer { width:50%;margin:0;padding:10px 0 0 10px } #mapdivouter { position:fixed;width:50%;left:50%;top:0;height:100%;} #mapdiv { width:100%;height:100%;} .Vorschaubild { width:100px; } .overlay_hidden { display: none } .overlay { top: 0; left: 0; width: 100%; height: 100%; position: absolute; display: table ; z-index:1000; background-color:rgb(0,0,0); background-color:rgba(0,0,0,0.3) } .overlay div { display: table-cell; vertical-align: middle; text-align:center } .overlay div div { border: 3px solid blue; padding:1em; background-color:#f0f8ff; display:inline-block; text-align:left } @media screen and (min-width:70em) and (min-height:30em) { .overlay { position: fixed; } } .overlay_visible { display:block; width:135%; max-width:60em; } .overlay_visible button { display:none } .overlay_visible span { font-weight:bold } #beschreibung div div { width:70% } .nofileapi .UI { display:none } #warning { display:none } .nofileapi #warning { display:block } #ausTrack { display:none } #savegpx { display:none } #make_save_gpx { display:none } #clipboard { display: none; position:fixed; top:0; left:0; width:calc(100vw - 100px); height:100vh; z-index:10; background-color:rgba(1,1,1,0.5); padding:20px 50px } #clipboard p { padding:10px } #clipboard textarea { width:calc(100vw - 128px);height:calc(100vh - 100px - 2.5em) } </style> </head> <body class="nofileapi"> <a id="skip-link" href="#outer">zum Hauptinhalt</a> <nav id="sitenav" aria-labelledby="sitenav-label"> <h2 id="sitenav-label" class="visually-hidden">Site-Navigation</h2> <details> <summary>Men眉</summary> <ul> <li><a href="/">Startseite</a> <li aria-current="page"> <details> <summary>Tools</summary> <ul> <li><a href="Ritzelrechner.html">Ritzelrechner</a></li> <li><a href="ShowGPX.html">Show GPX</a></li> <li aria-current="page"><a href="#">Wann und wo</a></li> <li><a href="week-rollover-korrektur.html">Week-Rollover-Fehler korrigieren</a></li> <li><a href="Energiekostenrechner.html">Energiekostenrechner</a></li> </ul> </details> <li> <details> <summary>Mathematik</summary> <ul> <li><a href="Spiralen.html">Spiralen</a></li> <li><a href="LogistischeAbbildung.html">Logistische Abbildung</a></li> <li><a href="Mandelbrotmenge.html">Mandelbrotmenge</a></li> <li><a href="Fouriersynthese.html">Fouriersynthese</a></li> <li><a href="FktPlot.html">Funktionsplot</a></li> <li><a href="Buchstabenmixer.html">Buchstabenmixer</a></li> </ul> </details> <li><a href="Sudoku.html">Sudoku</a> <li><a href="Touren/">Touren</a> <li> <details> <summary>Scripte</summary> <ul> <li><a href="GPXViewer/">GPX Viewer</a></li> <li><a href="TableSort.html">Tabellensortierer</a></li> </ul> </details> <li><a href="Impressum.html">Impressum</a></li> </ul> </details> </nav> <script src="menu.js"></script> <div id="outer"> <h1>Wann und wo wurde das Foto aufgenommen?<br>Online Geotagger</h1> <p><button type="button" onclick="document.getElementById('beschreibung').className='overlay'">Beschreibung</button></p> <p class="UI"><label>Bitte Foto(s) ausw盲hlen: <input type="file" multiple id="fi" onchange="im_file_input()"></label></p> <p class="UI" id="ausTrack">Es wurden Bilder ohne GPS-Koordinaten gefunden. Um diese mit einem Track zu verorten, <label>bitte GPX-Datei(en) ausw盲hlen: <input type="file" multiple id="figpx" onchange="gpx_file_input()"></label> <label><br>Zeitdifferenz: <input type="text" id="tdiff" value="0" size=3 onchange="gpx_file_input()"> Minuten, </label> <label>Korrektor Week-Rollover: <select><option value="-2048">-2048</option><option value="-1024">-1024</option><option value="0" selected>0</option><option value="1024">1024</option><option value="2048">2048</option></select> Wochen</label></p> <p id="make_save_gpx" class="UI"> <button type="button" onclick="wp_pgx_output()">GPX-Datei mit Fotowegpunkten erstellen</button> <label for="useDataUrl">Bildaten als Wegpunktname: </label><input type="checkbox" id="useDataUrl"> <br><a id="savegpx" download="Fotos.gpx">und speichern</a> <br><button type="button" onclick="wp_html_output()">a-Tags mit Geodaten anzeigen</button> </p> <p id="warning">Ihr Browser unterst眉tzt nicht die File-API</p> <div id="trackinfo"></div> <div id="bildinfo"></div> </div> <div id="mapdivouter"><div id="mapdiv"></div></div> <div id="beschreibung" class="overlay"> <div><div> <h2>Beschreibung</h2> <p>Diese Seite sucht in einem Foto in den EXIF-Daten nach dem Aufnahmedatum und den GPS-Koordinaten des Aufnahmeorts und zeigt sie in einer Karte an (Geotagging). Es k枚nnen auch mehrere Fotos untersucht werden.</p> <p>Bei Fotos ohne GPS-Koordinaten in den EXIF-Daten kann der Aufnahmeort anhand der Aufnahmezeit 眉ber einen Track im GPX-Format ermittelt werden.</p> <p>Es kann auch eine GPX-Datei mit Wegpunkten f眉r die Bilder erzeugt werden. Die Option "Bildaten als Wegpunktname" sollte aber nur verwendet werden, wenn die Bilder auf eine f眉r das Internet vern眉nftige Gr枚脽e verkleinert wurden.</p> <p>Der GPX-Viewer unterst眉tzt auch die Anzeige von Bildern ohne GPX-Datei. Das dazu ben枚tigte HTML kann angezeigt und in die Zwischenablage kopiert werden.</p> <p>Die Anzeige erfolgt mit dem <a href="https://www.j-berkemeier.de/GPXViewer/">GPX-Viewer.</a></p> <p>Die Seite befindet sich noch im Teststadium, nicht alle Browser werden unterst眉tzt. Wenn irgendetwas nicht funktioniert, w眉rde ich mich 眉ber eine <a href="Impressum.html">R眉ckmeldung</a> freuen. Und wenn alles funktioniert nat眉rlich auch. <p style="margin-top:4em">Version vom 4. 12. 2021 <a href="https://www.j-berkemeier.de">J眉rgen Berkemeier</a></p> <p><button type="button" onclick="document.getElementById('beschreibung').className='overlay_hidden'">Schlie脽en</button></p> </div></div> </div> <div id="clipboard"> <p>Bitte Inhalt mit Strg C bzw. cmd C in die Zwischenablage kopieren <br><textarea id="ta"></textarea> <br><button type="button" onclick="this.parentNode.parentNode.style.display='none'">Schlie脽en</button> </p> </div> <script src="GPXViewer/GM_Utils/GPX2GM.js?autoload=false"></script> <script src="GPXViewer/GM_Utils/JBexif.js"></script> <script> var zustimmung = false; var first = true; var diff_zulu=37; // Differenz zwischen Zulu-Zeit und Greenich Time, Stand ab 1. 1. 2017 if(typeof(FileReader)=="function" || typeof(FileReader)=="object") { document.getElementById("fi").value = ""; document.getElementById("figpx").value = ""; document.body.className = ""; document.getElementById('beschreibung').className = "overlay_visible"; var Fullscreenbutton = true; var Wpcluster = true; var map,_map,mapdiv; var markers = []; JB.Debug_Info("","GPXViewer "+JB.GPX2GM.ver+" vom "+JB.GPX2GM.dat,false); JB.LoadCSS(JB.GPX2GM.Path+"GPX2GM.css"); JB.LoadScript(JB.GPX2GM.Path+"GPX2GM_Defs.js", function() { JB.Scripte.GPX2GM_Defs = 2; Mapapi = JB.GPX2GM.check_API(); JB.GPX2GM.setparameters(); if(JB.GPX2GM.GM_usage_ok()) { zustimmung = true; JB.icons = new JB.Icons(JB.GPX2GM.Path); JB.Debug_Info("Start","Icons vorbereitet",false); JB.Scripte.maputils = 1; if(JB.GPX2GM.parameters.mapapi=="gm") { if(location.protocol == "file:") JB.LoadScript("https://maps.google.com/maps/api/js?callback=JB.gmcb", function() {} ); else JB.LoadScript("https://maps.google.com/maps/api/js?key=AIzaSyBpn-EB9zTc7b-tKl_qCAeBqDta5Gha3AA&callback=JB.gmcb", function() {} ); JB.LoadScript(JB.GPX2GM.Path+"gmutils.js", function() { JB.Scripte.maputils = 2; } ); } else { JB.LoadScript(JB.GPX2GM.Path+"leaflet/leaflet.js", function() { JB.Scripte.maplib = 2; }); JB.LoadCSS(JB.GPX2GM.Path+"leaflet/leaflet.css"); JB.LoadScript(JB.GPX2GM.Path+"osmutils.js", function() { JB.Scripte.maputils = 2; } ); } } }); var bildinfo = document.querySelector("#bildinfo"); var trackinfo = document.querySelector("#trackinfo"); var ausTrack = document.querySelector("#ausTrack"); var savegpx = document.querySelector("#savegpx"); var make_save_gpx = document.querySelector("#make_save_gpx"); var imgInfo = {}; var exif_cb = function(exif) { imgInfo[exif.fname].load = true; imgInfo[exif.fname].latlon = { ok: false }; if(exif.hasGPS) { imgInfo[exif.fname].latlon = exif.readLatLon(); if(Math.abs(imgInfo[exif.fname].latlon.lat)<1000 && Math.abs(imgInfo[exif.fname].latlon.lon)<1000) imgInfo[exif.fname].latlon.ok = true; } if(exif.hasExif) { var dt = exif.date_time(); // console.log("dt",JSON.stringify(dt)); imgInfo[exif.fname].date_time = dt; var date = new Date(dt.year, dt.month-1, dt.day, dt.hour, dt.minute, dt.second); imgInfo[exif.fname].time = date.getTime()/1000; } imgInfo[exif.fname].dataUrl = exif.dataUrl; imgInfo[exif.fname].hasExif = exif.hasExif; imgInfo[exif.fname].hasGPS = exif.hasGPS; imgInfo[exif.fname].error = exif.error; imgInfo[exif.fname].description = exif.readDescription(); } var check_img_interval; var check_img = function() { var allflag = true; var allhaslatlon = true; var onehaslatlon = false; for(var im in imgInfo) { allflag &= imgInfo[im].load; if(allflag) { allhaslatlon &= imgInfo[im].latlon.ok; onehaslatlon |= imgInfo[im].latlon.ok; } } if(allflag) { if(onehaslatlon) make_save_gpx.style.display="block"; if(allhaslatlon) { ausTrack.style.display="none"; } else { ausTrack.style.display="block"; } window.clearInterval(check_img_interval); show_im_data(); } } var show_im_data = function() { var latmin = 1000, lonmin = 1000, latmax = -1000, lonmax = -1000; for(var im in imgInfo) { if(imgInfo[im].hasGPS && Math.abs(imgInfo[im].latlon.lat)<1000 && Math.abs(imgInfo[im].latlon.lon)<1000) { if(imgInfo[im].latlon.lat<latmin) latmin = imgInfo[im].latlon.lat; if(imgInfo[im].latlon.lat>latmax) latmax = imgInfo[im].latlon.lat; if(imgInfo[im].latlon.lon<lonmin) lonmin = imgInfo[im].latlon.lon; if(imgInfo[im].latlon.lon>lonmax) lonmax = imgInfo[im].latlon.lon; } } if(latmin == latmax) { latmin -= .001; latmax += .001; } if(lonmin == lonmax) { lonmin -= .001; lonmax += .001; } if(latmin == 1000) { latmin = -80; latmax = 80; lonmin = -170; lonmax = 170; } bildinfo.innerHTML = ""; var sh_img = function(src,ele) { var imele = document.createElement("img"); imele.onload = function() { var imh = this.height; var imw = this.width; imele.height = Math.round(100*imh/imw); } imele.src = src; imele.style.imageOrientation = "from-image"; ele.appendChild(imele); } /*var sh_img = function(src,ele) { var imobj = new Image(); var canele = document.createElement("canvas"); var context = canele.getContext('2d'); canele.width = canele.height = 100; imobj.onload = function() { var imh = this.height; var imw = this.width; var canh = Math.round(100*imh/imw); canele.height = canh; context.drawImage(this,0,0,100,canh); } imobj.src = src; ele.appendChild(canele); }*/ for(var im in imgInfo) { var pele = document.createElement("p"); if(imgInfo[im].dataUrl /*&& imgInfo[im].dataUrl.length<2000000*/) { sh_img(imgInfo[im].dataUrl,pele); } pele.appendChild(document.createTextNode("Datei: " + im)); pele.appendChild(document.createElement("br")); if(imgInfo[im].hasExif) { pele.appendChild(document.createTextNode("Aufnahmedatum: " + imgInfo[im].date_time.string)) pele.appendChild(document.createElement("br")); } if(imgInfo[im].hasGPS) pele.appendChild(document.createTextNode("Aufnahmeort: Breite: " + imgInfo[im].latlon.lat + ", L盲nge: " + imgInfo[im].latlon.lon)); if(imgInfo[im].description.length) { pele.appendChild(document.createElement("br")); pele.appendChild(document.createTextNode("Bildbeschreibung:")); pele.appendChild(document.createElement("br")); pele.appendChild(document.createTextNode(imgInfo[im].description)); } if(imgInfo[im].error.length) { pele.appendChild(document.createElement("br")); pele.appendChild(document.createTextNode(imgInfo[im].error)); pele.appendChild(document.createElement("br")); } bildinfo.appendChild(pele); } if(JB.Scripte.maplib==2) { if(!zustimmung) return; if(first) { first = false; mapdiv = document.getElementById("mapdiv"); map = new JB.makeMap("mapdiv"); map.mapdiv = mapdiv, map.id = "Wann und wo"; _map = new JB.Map(map); } else { for(var i=0;i<markers.length;i++) JB.RemoveElement(markers[i]); markers = []; } _map.rescale({latmin:latmin,latmax:latmax,lonmin:lonmin,lonmax:lonmax}); _map.change("OSMDE"); for(var im in imgInfo) { if(imgInfo[im].hasGPS && Math.abs(imgInfo[im].latlon.lat)<1000 && Math.abs(imgInfo[im].latlon.lon)<1000) { if(imgInfo[im].dataUrl) markers = markers.concat(_map.Marker_Bild({lat:imgInfo[im].latlon.lat,lon:imgInfo[im].latlon.lon,info:imgInfo[im].description},JB.icons.Bild,imgInfo[im].dataUrl,im)); else markers = markers.concat(_map.Marker_Bild({lat:imgInfo[im].latlon.lat,lon:imgInfo[im].latlon.lon},JB.icons.Bild,im,im)); } } } } var trimmNumber = function(n) { if(n<10) n = "0" + n; return n; } var wp_html_output = function() { var html=""; for(var im in imgInfo) { var ii = imgInfo[im]; if(ii.hasGPS && Math.abs(ii.latlon.lat)<1000 && Math.abs(ii.latlon.lon)<1000) { html += "<img src='" + im + "' alt='" + ii.description + "' data-geo='lat:" + ii.latlon.lat + ",lon:" + ii.latlon.lon + "' />\n"; // html += "<a href='" + im + "' data-geo='lat:" + ii.latlon.lat + ",lon:" + ii.latlon.lon + "'></a>\n"; } } copy2clipboard(html); } var copy2clipboard = function(text) { document.getElementById("clipboard").style.display = "block"; var ta = document.getElementById("ta"); ta.value = text; ta.focus(); ta.select(); //window.prompt("Copy to clipboard: Ctrl+C, Enter", text); } var wp_pgx_output = function() { // var info_im = new Image(); // info_im.src = "bl.gif?GPX-File_Output"; // Probleme s. http://forum.de.selfhtml.org/my/?t=216056&m=1480539 var useDataUrl = document.querySelector("#useDataUrl").checked; var gpx = "" + '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n' + '<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="http://www.j-berkemeier.de/Wann_und_wo.html" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">\n'; for(var im in imgInfo) { var ii = imgInfo[im]; if(ii.hasGPS && Math.abs(ii.latlon.lat)<1000 && Math.abs(ii.latlon.lon)<1000) { gpx += '<wpt lat="'+ii.latlon.lat+'" lon="'+ii.latlon.lon+'">\n'; var dt = ii.date_time; var date = new Date(dt.year, dt.month-1, dt.day, dt.hour, dt.minute, dt.second); date.setTime(date.getTime()+diff_zulu*1000); gpx += ' <time>' +date.getUTCFullYear()+'-'+trimmNumber(date.getUTCMonth()+1)+'-'+trimmNumber(date.getUTCDate())+'T' +trimmNumber(date.getUTCHours())+':'+trimmNumber(date.getUTCMinutes())+':'+trimmNumber(date.getUTCSeconds())+'Z</time>\n'; if(useDataUrl) gpx += ' <name><![CDATA['+ii.dataUrl+']]></name>\n'; else gpx += ' <name>'+im+'</name>\n'; if(ii.description) gpx += ' <cmt>' + ii.description + '</cmt>\n'; gpx += ' <sym>Scenic Area</sym>\n'; gpx += '</wpt>\n'; } } gpx += '</gpx>'; saveFile("fotos.gpx",gpx) } var saveFile = function(filename,daten) { window.URL = window.URL || window.webkitURL; if(window.URL) { var gpx_blob = new Blob([daten], {type:'text/plain'}); var a = document.createElement("a"); a.download = filename; a.href = window.URL.createObjectURL(gpx_blob); document.body.appendChild(a); a.click(); document.body.removeChild(a); } else { var fenster = window.open("about:blank","GPX"); fenster.document.write(daten.replace(/</g,"<")); } } var im_file_input = function() { // var info_im = new Image(); // info_im.src = "bl.gif?File_Input"; document.getElementById('beschreibung').className = 'overlay_hidden'; document.getElementById("figpx").value = ""; bildinfo.innerHTML = ""; trackinfo.innerHTML = ""; make_save_gpx.style.display="none"; var fin = document.getElementById("fi").files; if(fin) { check_img_interval = window.setInterval(check_img,200); imgInfo = {}; for(var i=0;i<fin.length;i++) { imgInfo[fin[i].name] = {}; imgInfo[fin[i].name].load = false; new JB.exif({name:fin[i].name,fileobject:fin[i]},exif_cb); } } } var gpx_file_input = function() { // var info_im = new Image(); // info_im.src = "bl.gif?GPX-File_Input"; document.getElementById('beschreibung').className = 'overlay_hidden'; var fin = document.getElementById("figpx").files; var toff = document.getElementById("tdiff").value * 60; if(fin && fin.length) { var file = []; trackinfo.innerHTML = ""; for(var i=0;i<fin.length;i++) { file[i] = { name:fin[i].name , fileobject:fin[i] }; trackinfo.innerHTML += fin[i].name + " "; } trackinfo.innerHTML += "<br>"; JB.lpgpx.call(map,file,"gpxfile",function(gpxdaten) { var tracks = gpxdaten.tracks.track; for(var t=0;t<tracks.length;t++) { var daten = tracks[t].daten; trackinfo.innerHTML += "Track " + t + "<br>"; trackinfo.innerHTML += "Startzeit: " + JB.sec2string.call(map,daten[0].tabs*3600,0) +"<br>"; trackinfo.innerHTML += "Endzeit: " + JB.sec2string.call(map,daten[daten.length-1].tabs*3600,0) +"<br>"; } for(var im in imgInfo) { var ii = imgInfo[im]; var im_time = ii.time - toff + diff_zulu; //console.log(im); //console.log(ii.time+"\n"+im_time+"\n"+tracks[0].daten[0].tabs*3600+"\n"+tracks[0].daten[daten.length-1].tabs*3600); // ---!!!--- //console.log(ii.hasGPS,ii.latlon.ok); if( /*ii.hasGPS &&*/ !ii.latlon.ok ) { ii.latlon.lat = 10000; ii.latlon.lon = 10000; ii.hasGPS = false; for(var t=0;t<tracks.length;t++) { var daten = tracks[t].daten; for(var i=0;i<daten.length;i++) { //console.log(im_time, daten[i].tabs*3600); if(im_time < daten[i].tabs*3600) break; } if(i>0 && i<daten.length) { // L盲nge und Breite interpolieren var fak = (im_time-daten[i-1].tabs*3600)/(daten[i].tabs*3600-daten[i-1].tabs*3600); ii.latlon.lat = daten[i-1].lat + fak * (daten[i].lat-daten[i-1].lat); ii.latlon.lon = daten[i-1].lon + fak * (daten[i].lon-daten[i-1].lon); ii.hasGPS = true; } } } //console.log(ii.hasGPS); } make_save_gpx.style.display="block"; show_im_data(); }); } } } </script> </body> </html>