是否可以从图像中获取图像 GPS 位置坐标?
Is possible to get Image GPS location coordinates from the Image?
我正在构建一个 Flutter 应用程序,用户可以在其中 post 一张照片及其位置。用户既可以从相机中获取图片,也可以从图库中获取图片。
如果用户用相机拍照,我可以使用设备的 GPS 位置来设置照片的位置。我正在尝试根据图片的元数据获取图片的 GSP 位置,但是,我还没有找到方法。
可以吗?最好的方法是什么?
编辑:我把 "GPS" 放在问题中以使其清楚。我试图找出拍摄照片的物理位置。我还在问题中添加了 "Flutter" 以明确我正面临在 Flutter App 中解决此问题的问题。
如果图像是 JPEG 或 RAW 图像文件,则地理位置元数据将存储为 Exif 标签。在 Android 中,这是通过 ExifInterface
class.
完成的
标签是TAG_GPS_LATITUDE
和TAG_GPS_LONGITUDE
:
https://developer.android.com/reference/android/media/ExifInterface.html
请注意坐标需要以有理格式表示:度分秒,如dd/1,mm/1,ss/1
.
我发现我之前的问题与设备的相机权限有关。通常 android 的相机会访问用户位置并将 GPS 坐标保存为 Exif 标签,但 ios 设备通常不会默认保存此信息,除非用户允许相机应用程序的位置权限。
我更改了我的应用程序以检查图像是否具有 GPS 坐标,并且用户决定是否要共享他的实际位置或图像位置。
我还必须做一些数学运算来处理坐标:
为了使用代码,您必须将包 exif 和 geoflutterfire 添加到您的应用中。
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);
}
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);
}
}
我正在构建一个 Flutter 应用程序,用户可以在其中 post 一张照片及其位置。用户既可以从相机中获取图片,也可以从图库中获取图片。
如果用户用相机拍照,我可以使用设备的 GPS 位置来设置照片的位置。我正在尝试根据图片的元数据获取图片的 GSP 位置,但是,我还没有找到方法。
可以吗?最好的方法是什么?
编辑:我把 "GPS" 放在问题中以使其清楚。我试图找出拍摄照片的物理位置。我还在问题中添加了 "Flutter" 以明确我正面临在 Flutter App 中解决此问题的问题。
如果图像是 JPEG 或 RAW 图像文件,则地理位置元数据将存储为 Exif 标签。在 Android 中,这是通过 ExifInterface
class.
标签是TAG_GPS_LATITUDE
和TAG_GPS_LONGITUDE
:
https://developer.android.com/reference/android/media/ExifInterface.html
请注意坐标需要以有理格式表示:度分秒,如dd/1,mm/1,ss/1
.
我发现我之前的问题与设备的相机权限有关。通常 android 的相机会访问用户位置并将 GPS 坐标保存为 Exif 标签,但 ios 设备通常不会默认保存此信息,除非用户允许相机应用程序的位置权限。
我更改了我的应用程序以检查图像是否具有 GPS 坐标,并且用户决定是否要共享他的实际位置或图像位置。
我还必须做一些数学运算来处理坐标:
为了使用代码,您必须将包 exif 和 geoflutterfire 添加到您的应用中。
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);
}
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);
}
}