Felipe César
Felipe César

Reputation: 1444

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.

Upvotes: 11

Views: 14017

Answers (4)

EmsD
EmsD

Reputation: 21

You can also now use flutter native_exif package to to get the coordinates if available.


      Future<GeoPoint?> getLocationDataFromImage(String filePath) async {
        GeoPoint? preciseLocation;
        final exif = await Exif.fromPath(filePath);
        final latLong = await exif.getLatLong();
        await exif.close();
        if (latLong != null) {
          preciseLocation = GeoPoint(latLong.latitude, latLong.longitude);
          return preciseLocation;
        }
        return null;
      }

Upvotes: 1

exifLatitudeLongitudePoint(var data) async{
if (data.containsKey('GPS GPSLongitude')) {
  final gpsLatitude = data['GPS GPSLatitude'];
  final latitudeSignal = data['GPS GPSLatitudeRef']!.printable;
  List latitudeRation = gpsLatitude!.values.toList();
  List latitudeValue = latitudeRation.map((item) {
    return (item.numerator.toDouble() / item.denominator.toDouble());
  }).toList();
  double latitude = latitudeValue[0] + (latitudeValue[1] / 60) + (latitudeValue[2] / 3600);
  if (latitudeSignal == 'S') latitude = -latitude;
  latValue(latitude);

  final gpsLongitude = data['GPS GPSLongitude'];
  final longitudeSignal = data['GPS GPSLongitude']!.printable;
  List longitudeRation = gpsLongitude!.values.toList();
  List longitudeValue = longitudeRation.map((item) {
    return (item.numerator.toDouble() / item.denominator.toDouble());
  }).toList();
  double longitude =longitudeValue[0] + (longitudeValue[1] / 60) + (longitudeValue[2] / 3600);
  if (longitudeSignal == 'W') longitude = -longitude;
  lngValue(longitude);
}

}

Upvotes: 1

Felipe C&#233;sar
Felipe C&#233;sar

Reputation: 1444

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);
}

Upvotes: 7

LuisTavares
LuisTavares

Reputation: 2206

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.

Upvotes: 1

Related Questions