我正在为我的JPEG图像写GPS坐标,并且坐标是正确的(正如我的logcat输出所示),但似乎它以某种方式被破坏了。读取exif数据会产生空值,或者对于我的GPS:512.976698 degrees, 512.976698 degrees
。谁能解释一下这个问题?
写下来:
try {
ExifInterface exif = new ExifInterface(filename);
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, latitude);
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, longitude);
exif.saveAttributes();
Log.e("LATITUDE: ", latitude);
Log.e("LONGITUDE: ", longitude);
} catch (IOException e) {
e.printStackTrace();
}
并阅读它:
try {
ExifInterface exif = new ExifInterface("/sdcard/globetrotter/mytags/"+ TAGS[position]);
Log.e("LATITUDE EXTRACTED", exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
Log.e("LONGITUDE EXTRACTED", exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
} catch (IOException e) {
e.printStackTrace();
}
它进入(例如)37.715183
,-117.260489
并出现33619970/65540, 14811136/3368550
,33619970/65540, 14811136/3368550
。我做错了吗?
编辑:
所以,问题是我没有用正确定义的格式对其进行编码,这就像你在这里看到的那样:
任何人都可以解释这种格式是什么?显然第一个数字是22/1 = 22度,但我无法弄清楚如何计算那里的小数。
答案 0 :(得分:23)
GPSLatitude
表示纬度。纬度表示为3 给出学位的
RATIONAL
值, 分钟和秒。 如果纬度表示为度数, 分钟和秒,一种典型的格式 将是dd/1,mm/1,ss/1
。当度 和分钟用于和 例如,分钟的分数是 给出最多两位小数, 格式为dd/1,mmmm/100,0/1
。https://docs.google.com/viewer?url=http%3A%2F%2Fwww.exif.org%2FExif2-2.PDF
Android文档在没有说明的情况下指定了这一点:http://developer.android.com/reference/android/media/ExifInterface.html#TAG_GPS_LATITUDE
Exif数据是标准化的,GPS数据必须使用上述地理坐标(分钟,秒等)而不是分数进行编码。除非它在exif标签中以该格式编码,否则它不会粘住。
如何编码:http://en.wikipedia.org/wiki/Geographic_coordinate_conversion
如何解码:http://android-er.blogspot.com/2010/01/convert-exif-gps-info-to-degree-format.html
答案 1 :(得分:11)
以下是我为地理标记图片所做的一些代码。它尚未经过严格测试,但似乎没问题(JOSM编辑器和exiftool读取位置)。
ExifInterface exif = new ExifInterface(filePath.getAbsolutePath());
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, GPS.convert(latitude));
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, GPS.latitudeRef(latitude));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, GPS.convert(longitude));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, GPS.longitudeRef(longitude));
exif.saveAttributes();
GPS类就在这里。 (方法可以更短,但至少可读)
/*
* @author fabien
*/
public class GPS {
private static StringBuilder sb = new StringBuilder(20);
/**
* returns ref for latitude which is S or N.
* @param latitude
* @return S or N
*/
public static String latitudeRef(double latitude) {
return latitude<0.0d?"S":"N";
}
/**
* returns ref for latitude which is S or N.
* @param latitude
* @return S or N
*/
public static String longitudeRef(double longitude) {
return longitude<0.0d?"W":"E";
}
/**
* convert latitude into DMS (degree minute second) format. For instance<br/>
* -79.948862 becomes<br/>
* 79/1,56/1,55903/1000<br/>
* It works for latitude and longitude<br/>
* @param latitude could be longitude.
* @return
*/
synchronized public static final String convert(double latitude) {
latitude=Math.abs(latitude);
int degree = (int) latitude;
latitude *= 60;
latitude -= (degree * 60.0d);
int minute = (int) latitude;
latitude *= 60;
latitude -= (minute * 60.0d);
int second = (int) (latitude*1000.0d);
sb.setLength(0);
sb.append(degree);
sb.append("/1,");
sb.append(minute);
sb.append("/1,");
sb.append(second);
sb.append("/1000");
return sb.toString();
}
}
答案 2 :(得分:4)
其他答案提供了很好的背景信息甚至是一个例子。这不是问题的直接答案,但我想添加一个更简单的例子而不需要做任何数学运算。 Location类提供了一个很好的convert函数:
public String getLonGeoCoordinates(Location location) {
if (location == null) return "0/1,0/1,0/1000";
// You can adapt this to latitude very easily by passing location.getLatitude()
String[] degMinSec = Location.convert(location.getLongitude(), Location.FORMAT_SECONDS).split(":");
return degMinSec[0] + "/1," + degMinSec[1] + "/1," + degMinSec[2] + "/1000";
}
我将返回值存储在我的图像中,并且标记被解析得很好。您可以在此处查看您的图片和地理坐标:http://regex.info/exif.cgi
@ratanas评论翻译成代码:
public boolean storeGeoCoordsToImage(File imagePath, Location location) {
// Avoid NullPointer
if (imagePath == null || location == null) return false;
// If we use Location.convert(), we do not have to worry about absolute values.
try {
// c&p and adapted from @Fabyen (sorry for being lazy)
ExifInterface exif = new ExifInterface(imagePath.getAbsolutePath());
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, getLatGeoCoordinates(location));
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, location.getLatitude() < 0 ? "S" : "N");
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, getLonGeoCoordinates(location));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, location.getLongitude() < 0 ? "W" : "E");
exif.saveAttributes();
} catch (IOException e) {
// do something
return false;
}
// Data was likely written. For sure no NullPointer.
return true;
}
以下是一些不错的LatLong转换器:latlong.net
答案 3 :(得分:0)
ExifInterface exif = new ExifInterface(compressedImage.getPath());
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE,gpsTracker.dec2DMS(gpsTracker.getLatitude()));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE,gpsTracker.dec2DMS(gpsTracker.getLongitude()));
转换器双精度字符串
String dec2DMS(double coord) {
coord = coord > 0 ? coord : -coord;
String sOut = Integer.toString((int)coord) + "/1,";
coord = (coord % 1) * 60;
sOut = sOut + Integer.toString((int)coord) + "/1,";
coord = (coord % 1) * 60000;
sOut = sOut + Integer.toString((int)coord) + "/1000";
return sOut;
}
答案 4 :(得分:-1)
检查android源代码:https://android.googlesource.com/platform/frameworks/base/+/android-4.4.2_r2/core/java/android/hardware/Camera.java
/ ** *设置GPS经度坐标。这将存储在JPEG EXIF中 *标题。 * * @param经度GPS经度坐标。 * / public void setGpsLongitude(double longitude){ set(KEY_GPS_LONGITUDE,Double.toString(longitude)); }
所以它是直接打印,我的日志也支持它:ExifInterface.TAG_GPS_LONGITUDE:-121.0553966
我的结论是将其设置为直接打印很好。