Convert image GPS coordinates into location information

The problem

You want to extract GPS coordinates from image or video metadata (Exif data) and turn the coordinates into useful location information like addresses

Background

Digital cameras typically record all sorts of data about the image in a format known as Exchangeable image file format, (commonly known as "Exif"). This data includes things like what type of camera was used to make the image. If the camera is able to it, for example a camera on a mobile phone, it may also include information about the location the image was taken. The location information is recorded as GPS coordinates: longitude and latitude.

Converting geocoordinates (longitude, latitude) into location information is the process know as reverse geocoding.

You can pass coordinates to the OpenCage geocoding API to reverse geocode the coordinates and return information about the location.

The solution

The process of geocoding images follows a few basic steps.

  1. Load an Exif library
    You will need a way to extract the raw coordinates from the image. There are many open source libraries available, search for "Exif" in the relevant library collection for your language (CPAN, pypi, rubygems, etc).

  2. Use the library to extract the coordinates from the image
    Note that the image may no have coordinates. Make sure you check for this case.

  3. Convert the coordinates to decimal format
    Exif data stores coordinates in degree/minutes/seconds format. Most software however expects decimal degrees. Luckily conversion is not particularly difficult.

  4. Send the decimal coordinates to the OpenCage geocoding API
    We have SDKs for calling the OpenCage geocoding API. for over 30 other programming languages

  5. Examine the reponse, extract the information you need

Code Example

Here is a detailed javascript example. The logic will be the same in other languages.

To extract the Exif data from an image we use the open source library exif.js library from a CDN via

<script src="https://cdn.jsdelivr.net/npm/exif-js"></script>

<script>
// we need to turn degree, min, sec format into decimal
function DMS2DD(degrees, minutes, seconds, direction) {    
  var dd = degrees + (minutes/60) + (seconds/3600);
  if (direction == "S" || direction == "W") {
    dd = dd * -1; 
  }
  return dd;
}

// extract the coordinates from the image
function getCoords() {
  var img1 = document.getElementById("img1");
  return EXIF.getData(img1, function() {
    myData = this;

    // the image may not have coordinates
    if (myData.exifdata.GPSLatitude != null){

      // latitude in decimal
      var latDeg = myData.exifdata.GPSLatitude[0].numerator;
      var latMin = myData.exifdata.GPSLatitude[1].numerator;
      var latSec = myData.exifdata.GPSLatitude[2].numerator;
      var latDir = myData.exifdata.GPSLatitudeRef;
      var lat = DMS2DD(latDeg, latMin, latSec, latDir);

      // longitude in decimal
      var lngDeg = myData.exifdata.GPSLongitude[0].numerator;
      var lngMin = myData.exifdata.GPSLongitude[1].numerator;
      var lngSec = myData.exifdata.GPSLongitude[2].numerator;
      var lngDir = myData.exifdata.GPSLongitudeRef;
      var lng = DMS2DD(lngDeg, lngMin, lngSec, lngDir);

      return lat + ',' + lng;
    }
  });
}

function Geocode(coords){
  // do the geocoding via OpenCage
  var apikey = 'YOUR-API-KEY';
  var api_url = 'https://api.opencagedata.com/geocode/v1/json'

  var request_url = api_url
    + '?'
    + 'key=' + apikey
    + '&q=' + encodeURIComponent(coords)
    + '&pretty=1'
    + '&no_annotations=1';

  // see full list of required and optional parameters:
  // https://opencagedata.com/api#forward  
  var request = new XMLHttpRequest();
  request.open('GET', request_url, true);

  request.onload = function() {
    // see full list of possible response codes:
    // https://opencagedata.com/api#codes
    if (request.status === 200){  // Success!
      var data = JSON.parse(request.responseText);
      console.log(data.results[0].formatted); // print the location
    } else {
      console.log("unable to geocode! Response code: " + request.status);
      var data = JSON.parse(request.responseText);
      console.log('error msg: ' + data.status.message);
    }
  };
  request.onerror = function() {
    // There was a connection error of some sort
    console.log("unable to connect to server");        
  };
  request.send();  // make the request
}

var coords = getCoords();
console.log('coords from image: ' + coords);
if (coords != null){
  Geocode(coords);
}

</script>



Further Reading

Happy geocoding!

Start your free trial

2,500 API requests per day.

No credit card required.