Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is possible to get Image GPS location coordinates from the Image?

I'm building a Flutter App where the user can post a photo and it's location. The use can both get a picture from the camera or from the library.

If the user take a picture from camera I can use the GPS location of the device to set the picture's location. I'm trying to get the GSP location of the pictures based on its metadata, but, I didn't found a way to do it yet.

Is possible to do it? How the best way?

Edit: I put "GPS" in the question to make it clear. I'm trying to discover the physical position where the picture was taken. I also added "Flutter" to the question to make it clear that I'm facing the problem of solving this problem in a Flutter App.

like image 998
Felipe César Avatar asked Mar 08 '19 09:03

Felipe César


2 Answers

I discovered that my previous problem was related to the Camera permissions of the devices. Usually a camera from android access the user location and save the GPS coordinates as Exif tag, but the ios devices usually don't save this by default unless the user allows location permissions to the camera app.

I changed my app to check if the image has GPS coordinates and the user decides if he wants to share his actual location or the image location.

I'm also having to do some math to process the coordinates:

In order to you use the code you have to add the package exif and geoflutterfire to your app.

void _checkGPSData() async {
    Map<String, IfdTag> imgTags = await readExifFromBytes( File(image.path).readAsBytesSync() );

    if (imgTags.containsKey('GPS GPSLongitude')) {
      setState(() {
        _imgHasLocation = true;
        _imgLocation = exifGPSToGeoFirePoint(imgTags);
      });
    }

  }


GeoFirePoint exifGPSToGeoFirePoint(Map<String, IfdTag> tags) {

  final latitudeValue = tags['GPS GPSLatitude'].values.map<double>( (item) => (item.numerator.toDouble() / item.denominator.toDouble()) ).toList();
  final latitudeSignal = tags['GPS GPSLatitudeRef'].printable;


  final longitudeValue = tags['GPS GPSLongitude'].values.map<double>( (item) => (item.numerator.toDouble() / item.denominator.toDouble()) ).toList();
  final longitudeSignal = tags['GPS GPSLongitudeRef'].printable;

  double latitude = latitudeValue[0]
    + (latitudeValue[1] / 60)
    + (latitudeValue[2] / 3600);

  double longitude = longitudeValue[0]
    + (longitudeValue[1] / 60)
    + (longitudeValue[2] / 3600);

  if (latitudeSignal == 'S') latitude = -latitude;
  if (longitudeSignal == 'W') longitude = -longitude;

  return  GeoFirePoint(latitude, longitude);
}
like image 120
Felipe César Avatar answered Oct 18 '22 23:10

Felipe César


The geolocation metadata is stored as Exif tags provided the image is a JPEG or a RAW image file. In Android this is done through the ExifInterface class.

The tags are TAG_GPS_LATITUDE and TAG_GPS_LONGITUDE: https://developer.android.com/reference/android/media/ExifInterface.html

Please note the coordinates need to be expressed in the rational format: degrees, minutes and seconds, as dd/1,mm/1,ss/1.

like image 1
LuisTavares Avatar answered Oct 19 '22 00:10

LuisTavares