GPS座標をJPEG画像に書き込んでおり、座標は正しい(logcat出力で示されているように)が、何らかの理由で破損しているようです。 exifデータを読み取ると、null値になるか、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度ですが、そこでの小数の計算方法がわかりません。
GPSLatitude
緯度を示します。緯度は、度、分、秒をそれぞれ表す3つの
RATIONAL
値として表されます。緯度が度、分、秒で表される場合、一般的な形式はdd/1,mm/1,ss/1
。度と分が使用され、たとえば、分数の小数部が小数点以下2桁まで指定されている場合、形式はdd/1,mmmm/100,0/1
。https://docs.google.com/viewer?url=http%3A%2F%2Fwww.exif.org%2FExif2-2.PDF
Android docsは説明なしでこれを指定しています: 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
これが、写真にジオタグを付けるために行ったコードです。まだ十分にテストされていませんが、問題はないようです(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();
}
}
他の回答はニースの背景情報と例さえ提供しました。これは質問への直接の回答ではありませんが、計算を行わずにさらに簡単な例を追加したいと思います。 Location クラスは、Nice 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
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()));
コンバーターdoubleからストリング
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;
}