Geolokalizacja na przykładzie zdjęć - PHP + EXIF + Google Maps

Jeśli spotkałeś się ze stronami które pozwalają załadować zdjęcie i następnie pokazują mapę wraz z miejscem gdzie było zrobione, a nie wiesz na czym ta magia polega, to dobrze trafiłeś... Wszystko jest zasługą kilku nagłówków zapisanych w EXIF (Exchangeable Image File Format) oraz wbudowanego GPS w aparat lub telefon ;-) Jeśli chcesz sam zrobić taką stronę lub wykorzystać funkcjonalność to mam dla Ciebie gotową receptę.

Zacznę od kilku zdań wytłumaczenia... czym jest EXIF? jest to pewien standard metadanych dla zdjęć, czyli informacji którymi możemy opisać pliki graficzne. Np. robiąc zdjęcie Twój aparat może umieścić w nim takie dane jak:

  • model aparatu
  • ustawienia aparatu, czas naświetlenia, wartość przesłony, czułość matrycy w ISO czy ogniskowa obiektywu oraz położenie aparatu (pionowe/poziome)
  • datę wykonania zdjęcia
  • miniaturkę obrazka (to jest bardzo ciekawa funkcja i trzeba na nią uważać ;-) wymazując jakieś fragmenty ze zdjęcia miniaturka nie ulega modyfikacji, na niej te fragmenty zostaną bez zmian)
  • rozdzielczość w pikselach
  • współrzędne geograficzne
  • itd...

My skupimy się tylko na współrzędnych geograficznych (długość i szerokość). Ja dla poniższego przykładu wykorzystam PHP i rozszerzenie php-exif (w Ubuntu moduł jest automatycznie dodany do paczki).

Dane EXIF odczytujemy wykorzystując funkcję exif_read_data:

Zostanie nam zwrócona pełna struktura danych, informacji jest dość dużo, nas interesują jedynie:

["GPS"]=>
array(7) {
["GPSLatitudeRef"]=>
string(1) "N"
["GPSLatitude"]=>
array(3) {
[0]=>
string(4) "50/1"
[1]=>
string(7) "586/100"
[2]=>
string(3) "0/1"
}
["GPSLongitudeRef"]=>
string(1) "E"
["GPSLongitude"]=>
array(3) {
[0]=>
string(4) "19/1"
[1]=>
string(8) "5740/100"
[2]=>
string(3) "0/1"
}

Dane geolokalizacyjne zapisane są notacji sześćdziesiątkowej:

  • godzina
  • minuta
  • sekunda

Napiszmy więc funkcję która wyciągnie długość i szerokość geograficzną i przeliczy je na wartości na decymalne (dla nas chyba też bardziej zrozumiałe).

gps.php:

Funkcja wyciąga informacje GPS oraz dokonuje transformacji z systemu 60 na 10, po czym zwraca tablicę array(szerokosc, długosc):

Array
(
[0] => 50.097666666667
[1] => 19.956666666667
)

Mając te informacje możemy już wykorzystać Google Maps do prezentacji miejsca. Najszybciej możesz to zrobić, poprzez skopiowanie powyższej funkcji do pliku, np. gps.php, i stworzeniu pliku index.php który będzie go wykorzystywał:

index.php:

test.jpg - to nazwa pliku z którego odczytujemy wartości, możesz przerobić linijkę w pliku index.php:

$location = gps_from_exif("test.jpg");
na
$location = gps_from_exif($_GET['photo']);

co da Ci to możliwość podania w URLu nazwy pliku ze zdjęciem: http://twojastrona/index.php?photo=test.jpg

Po otworzeniu tej strony powinieneś zobaczyć mapę wraz z zaznaczoną lokalizacją zrobienia zdjęcia ;-)

Dlaczego odczytywanie współrzędnych ze zdjęć jest fajne? bo w Internecie jest mnóstwo zdjęć zrobionych np. telefonem iPhone, a Ty możesz zobaczyć gdzie mieszka ta pani z odbicia w lustrze... ;-)

  • tak na poprawke :) $location = gps_from_exif($_GET['photo']);

  • tomek

    w końcu jakiś wpis :)

  • @Bartek: oczywiście ;-) $_ gdzieś mi uciekło... już poprawione. ;-)

  • Poprawnie wyświetlają się tylko współrzędne NE.
    Żeby dobrze pokazywały się współrzędne z całego świata trzeba dodać minusy w przypadku półkuli S i półkuli W

    $lat = $szerokosc_h + $szerokosc_m / 60.0 + $szerokosc_s / 3600.0;
    $lng = $dlugosc_h + $dlugosc_m / 60.0 + $dlugosc_s / 3600.0;

    if($exif['GPS']['GPSLatitudeRef']=='S') $lat = -1 * $lat;
    if($exif['GPS']['GPSLongitudeRef']=='W') $lng = -1 * $lng;

    $gps_int = array($lat,$lng);

  • Bartek

    Przydało się, dzięki :)!