. Geotagging — привязка фотографий к карте
Geotagging — привязка фотографий к карте

Geotagging — привязка фотографий к карте

Уверен что про geotagging слышало подавляющее большинство хабраюзеров, особенно те кто интересуется фотографией. Для тех же, кто все таки не слышал поясню — в двух словах geotagging есть внедрение Exif тегов содержащих информацию с координатами GPS в фотографии с последующей привязкой фотографий к карте.

Возможность просмотра привязанных к картам фотографий предоставляет большинство современных фото-хостингов — PicasaWeb, Flickr, Яндекс-Фотки и прочие, да и десктопные программы подтягиваются, например Picasa.

Идеальный вариант для геотеггинга это приобретение специальных GPS-логгеров, тем более что цены на них в последнее время постоянно падают. Принцип действия GPS-логгеров прост до безобразия — устройство периодически сбрасывает текущие координаты на карту памяти, параллельно фотографируются фотки (желательно с включенной функцией «шедевр»). После фотосессии на фотки и трек с гео-логгера натравливается спец-софт, прописывающий в фотографии GPS координаты, синхронизируясь по времени.

Можно также использовать для этих целей коммуникатор с GPS — алгоритм аналогичен, хотя и не без минусов. Например, время работы коммуникатора, учитывая то что он не специально заточен под эти цели, оставляет желать лучшего. Но что делать если волшебного девайса нету, а фотки привязать к карте все-таки хочется?

Если все же сильно хочется, то можно залить фотографии на фотохостинг и вручную привязать их к карте, минус данного способа в том что на диске остаются фотографии без координат, да и делать что-то вручную не достойно правоверных айтишников/программистов с обостренной врожденной ленью.

Учитывая все вышенаписанное, было потрачено около часа времени на написание простого кода выдирающего GPS координаты с карты при щелчке мыши и прописывающего их в Exif фотографии.

Итак, задачу можно разделить на два этапа: 1. Вывод карты на экран и определение GPS координат. 2. Добавление тегов с GPS координатами в Exif информацию JPEG файла.

Вывод карты и определение GPS координат

Решить данную задачу при помощи Google Maps API гораздо проще чем может показаться на первый взгляд.

Создадим HTML файл с компонентом Google Maps, растянутым на весь экран без марджинов:

  1. <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
  2. < html xmlns ="http://www.w3.org/1999/xhtml" xmlns:v ="urn:schemas-microsoft-com:vml" >
  3. < head >
  4. < meta http-equiv ="content-type" content ="text/html; charset=UTF-8" />
  5. < title ></ title >
  6. < style type ="text/css" >
  7. body, html
  8. #map_canvas
  9. </ style >
  10. < script src
  11. type ="text/javascript" ></ script >
  12. <script type= "text/javascript" >
  13. var map;
  14. function initialize()
  15. </ script >
  16. </ head >
  17. < body onload ="initialize()" >
  18. < div id ="map_canvas" >
  19. </ div >
  20. </ body >
  21. </ html >

* Ключ для использования Google Maps API можно получить здесь, в примере используется ключ используемый в примерах в документации Maps API.

Загрузим файл в компонент WebBrowser (для удобства я поместил файл в ресурсы проекта):

  1. webBrowser.AllowWebBrowserDrop = false ;
  2. webBrowser.IsWebBrowserContextMenuEnabled = false ;
  3. webBrowser.WebBrowserShortcutsEnabled = false ;
  4. webBrowser.ObjectForScripting = this ;
  5. webBrowser.DocumentText = Resources.google;

Скомпилировав приложение на данном этапе, увидим следующее:

Добавим к компоненту карты возможность поиска, для этого включим GoogleBar, добавив следующий код к функции initialize():

  1. var mapOptions =
  2. // Включаем строку поиска
  3. map.enableGoogleBar();

Теперь добавим обработчик клика мыши на карте, для этого определим следующую функцию:

  1. // Обработчик клика по карте
  2. function getLatLng(overlay,latlng)
  3. >

И соответствюший listener в функцию initialize():

  1. GEvent.addListener(map, "click" , getLatLng);

Функция getLatLng() довольно проста. Сначала мы вычищаем все оверлеи с карты, создаем новый маркер с координатами места где пользователь кликнул по карте, ну и наконец, из эстетических соображений выводим popup с координатами.

Вот что у нас получилось:

Все выглядит красиво и юзабельно, но как же передать данные с координатами в приложение-хост (WinForms с компонентом WebBrowser)?

Для этого можно воспользоваться свойством WebBrowser.ObjectForScripting. Обьект присвоенный этому свойству доступен скриптам в странице как window.external. Замечу что обьект присваемый свойству ObjectForScripting (в данном случае обьект Form содержащий компонент WebBrowser) должен быть помечен аттрибутом ComVisible и в скриптах будут доступны только public методы и свойства.

Итак, добавим в функцию getLatLng() следуюшую строку:

  1. // Передача координат в хост-приложение
  2. window.external.SetValue(latlng.lat() + '|' + latlng.lng());

Как я уже сказал, доступ к обьекту присвоенному ObjectForScripting осуществляется через window.external, следовательно чтобы добавленный код заработал надо добавить в класс формы public метод SetValue(string):

  1. public void SetValue( string value )

Небольшое отступление, в методе SetValue используется класс GPSCoordinates.

Класс GPSCoordinates

Google Maps выдает координаты в десятичной форме, в Exif данные пишутся в виде массива байтов (об этом — ниже). Класс GPSCoordinates переводит десятичные GPS координаты в формат DMS (Degrees, Minutes, Seconds). Метод GetExifBytes() возвращает массив байтов подходящий для записи в Exif, об этом — в следующей части статьи.

  1. internal class GPSCoordinate