Heute wollte ich einmal testen, ob ich ohne Weiteres die Geoinformationen aus Bildern auslesen kann, die ich mit meinem iPhone 3G gemacht habe... Foto gemacht und auf den Rechner gezogen.
Wie komme ich aber nun für eine weitere Verarbeitung (zum Beispiel im Web) an die Informationen? Der Schlüssel lautet "Exchangeable image information" (kurz EXIF). Als PHP-Fuzzi tippte ich einfach mal php.net/exif ein und wurde prompt fündig:
function exif_read_data($filename) : array
Leider enthielt das zurückgegebene Array keine einfach weiter zu verwendenden Koordinaten, sondern leicht verworrene Infos:
[GPSLatitudeRef] => N
(
[0] => 52/1
[1] => 3367/100
[2] => 0/1
)
[GPSLongitudeRef] => E
(
[0] => 13/1
[1] => 2460/100
[2] => 0/1
)
Um diese Infos in Dezimalwerte zu überführen, kann man folgende Funktion nutzen:
function exifGeoCoordinateToDecimal
($reference,
array $coordinate) {
$prefix = $reference == 'S' || $reference == 'W' ? -1 : 1;
$a = $b > 0 ? $a / $b : $a;
$c = $d > 0 ? $c / $d : $c;
$e = $f > 0 ? $e / $f : $e;
return $prefix *
round(($a +
($c *
60 +
$e) /
3600),
6);
}
Und 1-fix-3 wird aus "52/1, 3367/100, 0/1 N" ein normaler Wert: 52.561167. Wem das nicht genug ist, hier eine fertige Variante zum Kopieren: geopoint.php
/**
* @author Florian Sternke, www.bananenhand.de/blog/
* @version 1.0.0.0
*/
class GeoPoint
{
/**
* Longitude
*
* @var double
*/
protected $dblLongitude = 0.0;
/**
* Latitude
*
* @var double
*/
protected $dblLatitude = 0.0;
/**
* Initialize an instance of GeoPoint
*
* @param double $dblLon Longitude
* @param double $dblLat Latitude
*/
public function __construct($dblLon, $dblLat)
{
// Option: check against a regexp to filter crap like 180.1
$this->dblLongitude = (double)$dblLon;
$this->dblLatitude = (double)$dblLat;
}
/**
* Output the point as string (lon,lat)
*
* Some strange people (like Google) display coordinates like
* y,x instead of the logical x,y-way (see cartesian coordinate
* system). If you prefer the first way, feel free to switch both...
*
* @return string
*/
public function __toString()
{
return "({$this->dblLongitude},{$this->dblLatitude})";
}
/**
* Returns the latitude of the geo coord
*
* @return double
*/
public function getLatitude()
{
return $this->dblLatitude;
}
/**
* Returns the longitude of the geo coord
*
* @return double
*/
public function getLongitude()
{
return $this->dblLongitude;
}
/**
* Transforms the EXIF geo cood array into a decimal format
*
* Array
* (
* [0] => 52/1
* [1] => 3367/100
* [2] => 0/1
* )
*
* to 52.561167
*
* @param string $reference N, E, W or S
* @param array $coordinate Coordinate
*/
protected
static function exifGeoCoordinateToDecimal
($reference,
array $coordinate) {
$prefix = $reference == 'S' || $reference == 'W' ? -1 : 1;
$a = $b > 0 ? $a / $b : $a;
$c = $d > 0 ? $c / $d : $c;
$e = $f > 0 ? $e / $f : $e;
return $prefix *
round(($a +
($c *
60 +
$e) /
3600),
6);
}
/**
* Reads an image file and returns the extracted geo information
*
* Reads an image file, transforms the exif geo information into
* a reusable geo point object
*
* @param string $strFilename File name
* @return GeoPoint
* @throws UnexpectedValueException, Exception
*/
public static function constructFromImageFile
($strFilename) {
{
{
$dblLat = self::exifGeoCoordinateToDecimal($arrInfos["GPSLatitudeRef"], $arrInfos["GPSLatitude"]);
$dblLon = self::exifGeoCoordinateToDecimal($arrInfos["GPSLongitudeRef"], $arrInfos["GPSLongitude"]);
return new self($dblLon, $dblLat);
}
else throw new UnexpectedValueException("Exchangeable image information (EXIF) without GPS data");
}
else throw new Exception("File not found");
}
}
echo GeoPoint::
constructFromImageFile("img_0013.jpg");