26

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 度ですが、小数の計算方法がわかりません。

4

5 に答える 5

25

GPS緯度

緯度を示します。RATIONAL 緯度は、それぞれ度、分、秒の3 つの値で表され ます。緯度が度、分、秒で表される場合、一般的な形式は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 ドキュメントでは、説明なしでこれを指定しています: 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

于 2011-03-12T05:02:26.000 に答える
18

写真にジオタグを付けるために行ったコードを次に示します。まだ十分にテストされていませんが、問題ないようです (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();
    }
}
于 2013-05-30T12:03:48.887 に答える
4

他の回答は、素晴らしい背景情報と例さえ提供しました。これは質問に対する直接的な回答ではありませんが、数学を行う必要のないさらに単純な例を追加したいと思います。Locationクラスは、優れた変換関数を提供します

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

于 2015-11-02T10:32:57.923 に答える
-1

Android ソース コードを確認してください: https://android.googlesource.com/platform/frameworks/base/+/android-4.4.2_r2/core/java/android/hardware/Camera.java

/** * GPS 経度座標を設定します。これは JPEG EXIF * ヘッダーに保存されます。* * @param longitude GPS 経度座標。*/ public void setGpsLongitude(double longitude) { set(KEY_GPS_LONGITUDE, Double.toString(longitude)); }

私のログもそれをサポートしています: ExifInterface.TAG_GPS_LONGITUDE : -121.0553966

私の結論は、直接印刷で問題ないということです。

于 2014-04-11T01:12:36.763 に答える