I am writing GPS coordinates to my JPEG image, and the coordinates are correct (as demonstrated by my logcat output) but it appears that it's being corrupted somehow. Reading the exif data results in either null values or, in the case of my GPS: 512.976698 degrees, 512.976698 degrees
. Can anyone shed some light on this problem?
writing it:
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(); }
and reading it:
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(); }
It goes in (for example) 37.715183
, -117.260489
and comes out 33619970/65540, 14811136/3368550
, 33619970/65540, 14811136/3368550
. Am I doing it wrong?
EDIT:
So, the problem is I am not encoding it in the properly defined format, which is something like you see here:
Can anyone explain what this format is? Obviously the first number is 22/1 = 22 degrees, but I can't figure out how to compute the decimal there.
In Windows, all you have to do is right-click a picture file, select “Properties,” and then click the “Details” tab in the properties window. Look for the Latitude and Longitude coordinates under GPS.
For Android users, Google Maps is the simplest way to either enter latitude and longitude coordinates or to find out your current coordinates. If you want to find your current coordinates, zoom into your location and hold down on the touchpad screen in the map.
GPSLatitude
Indicates the latitude. The latitude is expressed as three
RATIONAL
values giving the degrees, minutes, and seconds, respectively. If latitude is expressed as degrees, minutes and seconds, a typical format would bedd/1,mm/1,ss/1
. When degrees and minutes are used and, for example, fractions of minutes are given up to two decimal places, the format would bedd/1,mmmm/100,0/1
.https://docs.google.com/viewer?url=http%3A%2F%2Fwww.exif.org%2FExif2-2.PDF
The Android docs specify this without explanation: http://developer.android.com/reference/android/media/ExifInterface.html#TAG_GPS_LATITUDE
Exif data is standardized, and GPS data must be encoded using geographical coordinates (minutes, seconds, etc) described above instead of a fraction. Unless it's encoded in that format in the exif tag, it won't stick.
How to encode: http://en.wikipedia.org/wiki/Geographic_coordinate_conversion
How to decode: http://android-er.blogspot.com/2010/01/convert-exif-gps-info-to-degree-format.html
Here is some code I've done to geotag my pictures. It's not heavily tested yet, but it seems to be ok (JOSM editor and exiftool read location).
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();
And class GPS is here. (method could be shorter, but it's readable at least)
/* * @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(); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With