2006-12-13
Fotos, EXIF-Infos, GPS, Google Maps etc…
Nachdem ich vor ca. zwei Wochen Mätthu geholfen hatte, einen Skript zu schreiben, mit dem er in Google Maps zeigen konnte, wo er ein bestimmtes Foto gemacht hat, habe ich diese Woche das selbe in mein Album eingebaut.
JPG-Dateien von Digital-Kameras können Meta-Daten enthalten, wie z.B. Belichtungszeit, Blende, ob der Blitz eingesetzt wurde, etc. Diese Daten werden innerhalb der JPG-Daten im EXIF-Format abgelegt. Seit Version 2.2 des EXIF-Standards ist möglich, in den Meta-Daten eine geografische Position und andere von einem GPS-Empfänger gelieferte Daten zu speichern.
Meine Skripts ermöglichen es nun, die Position auf einer Google Map darzustellen.
Zu Beginn stehen einige JavaScript-Funktionen:
// Convert a decimal degree value to degress, minutes and seconds
function decToDMS(dec) {
var deg = Math.floor(dec);
dec = (dec - deg) * 60;
var min = Math.floor(dec);
var sec = (dec - min) * 60;
sec = Math.round(100 * sec) / 100; // round to 1/100th precision
return deg + "° " + min + "′ " + sec + "″";
}
// Convert latitude and longitude to a HTML string
function LatLngToHtml(lat, lng) {
lat = decToDMS(Math.abs(lat)) + (lat < 0 ? ' S' : ' N');
lng = decToDMS(Math.abs(lng)) + (lng < 0 ? ' W' : ' E');
return lat + ', ' + lng;
}
// Create a marker at the given point with the given label
function GMcreateMarker(point, label) {
var marker = new GMarker(point);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(label);
});
return marker;
}
// Initialize a map and return it
function GMinit(mapid) {
var div = document.getElementById(mapid);
if (!div) {
alert("Map region not found");
return null;
}
if (!GBrowserIsCompatible()) {
div.innerHTML = '<p>Sorry, your browser is not compatible with Google Maps.</p>';
return null;
}
var map = new GMap2(div);
if (parseInt(div.style.height) >= 350) {
map.addControl(new GOverviewMapControl());
map.addControl(new GLargeMapControl());
map.addControl(new GScaleControl());
}
else
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
// map.enableDoubleClickZoom();
map.setCenter(new GLatLng(47.2, 7.5), 8);
// Allow to click anywhere and display the clicked point's coordinates
GEvent.addListener(map, 'click', function(obj, point) {
map.lastPoint = point; // Keep a copy for the main page
if (point)
this.openInfoWindowHtml(point, LatLngToHtml(point.lat(), point.lng()));
});
// Add a new member function that creates labeled markers
map.addMarkerOverlay = function(lat, lng, label) {
var point = new GLatLng(lat, lng);
this.addOverlay(GMcreateMarker(point, label));
return point;
}
// Register the cleanup function
window.onunload = GUnload;
return map;
}
Die Funktion GMinit wird aus dem onload() Event aufgerufen und gibt
ein GMap2-Objekt aus dem Google Map API zurück, das um eine Methode
addMarkerOverlay() erweitert ist. Diese Methode erleichtert das Anzeigen
von Popup-Meldungen.
Weiter gehts mit einigen PHP-Funktionen zum Auslesen der EXIF-Informationen:
// Utility functions dealing with GPS coordinates from EXIF data
define(NO_ALTITUDE, -1024);
// Convert a lat or lon 3-array to decimal degrees
function exif_degrees($a) {
@eval("$deg = $a[0]; $min = $a[1]; $sec = $a[2];");
return $deg + $min / 60.0 + $sec / 3600.0;
}
// Extract lat, lon and altitude from an EXIF GPS array
function exif_gps_vars($exif, &$lat, &$lon, &$alt) {
$lat = exif_degrees($exif['GPS']['GPSLatitude']);
if ($exif['GPS']['GPSLatitudeRef'] == 'S')
$lat *= -1;
$lon = exif_degrees($exif['GPS']['GPSLongitude']);
if ($exif['GPS']['GPSLongitudeRef'] == 'W')
$lon *= -1;
if (isset($exif['GPS']['GPSAltitude']))
@eval("$alt = {$exif['GPS']['GPSAltitude']};");
else
$alt = NO_ALTITUDE;
}
// Convert decimal degrees to deg° min' sec" H
function exif_dec_to_DMS($dec, $hemi_pos, $hemi_neg) {
$absdec = abs($dec);
$deg = intval($absdec);
$absdec = ($absdec - $deg) * 60;
$min = intval($absdec);
$sec = ($absdec - $min) * 60;
return sprintf("%d° %02d′ %05.2f″ %s",
$deg, $min, $sec, $dec >= 0 ? $hemi_pos : $hemi_neg
);
}
// Convert an EXIF GPS array to HTML-usable text
function exif_to_html($exif) {
exif_gps_vars($exif, $lat, $lon, $alt);
$lat = exif_dec_to_DMS($lat, 'N', 'S');
$lon = exif_dec_to_DMS($lon, 'E', 'W');
$alt = intval($alt);
return "$lat, $lon" . ($alt == NO_ALTITUDE ? '' : " ($alt m)");
}
Diese Funktionen werden in der Karten-Seite zusammengesetzt:
PHP-Code:
$def_image = '/pic/glasses.jpg';
$image = isset($_GET['image']) ? $_GET['image'] : $def_image;
function image_exif_gps($file) {
if (
($exif = @exif_read_data($_SERVER['DOCUMENT_ROOT'] . '/' . $file, 0, true)) !== false &&
$exif['GPS']
) {
exif_gps_vars($exif, $lat, $lon, $alt);
// Return a JavaScript dictionary containing all useful GPS info
return "{isValid: true, lat: $lat, lon: $lon, alt: $alt, file: \"$file\"}";
}
else
return "{isValid: false, file: \"$file\"}";
}
JavaScript-Code:
var gmap;
window.onload = function() {
if (gmap = GMinit('map')) {
gmap.addMarkerOverlay(47.0452, 7.2713, 'Home, sweet home!');
var gps = gmap.gps = <?php echo image_exif_gps($image) ?>;
if (gps.isValid)
gmap.setCenter(
gmap.addMarkerOverlay(gps.lat, gps.lon, LatLngToHtml(gps.lat, gps.lon)),
14, G_SATELLITE_MAP
);
}
}
Das Besondere dabei ist, dass die PHP-Funktion image_exif_gps()
dynamisch ein JavaScript-Objekt generiert, das die GPS-Koordinaten enthält.
Den Update-Mechanismus beschreibe ich in einem nächsten Post.
Update: Hier gibts den versprochenen Update der GPS-Position im Bild.
23:33
[/software/php]
exif_gps_gmap
Google
Trackback
Tags:
gps
exif
jpeg
google maps
php
javascript