# How to parse EXIF GPS information to lat,lng decimal numbers

"EXIF_GPSAltitude": "(220.279)",
"EXIF_GPSLatitude": "(55) (40.711) (0)",
"EXIF_GPSLatitudeRef": "N",
"EXIF_GPSLongitude": "(8) (30.2282) (0)",

How should i understand the above example as degree, min, sec?

Some EXIF data that I extracted has metadata listed as above. Are these formats specified anywhere? Or should I expect a lot of different formats of gps positions in EXIF?

I need to write a method that gives the lat,lng as decimal numbers based on EXIF data, and I am unsure about how many different formats I should expect to be able to parse (I will learn this over time) and this question is mostly about the above examples. I know the degree is 55 and 8, but not sure if its 30 mins and 0.22*60 secs, and in that case, why is the 0 there?

• What OS? You might be interested in exiftool sno.phy.queensu.ca/~phil/exiftool . There is an executable for Win or Mac that I've used successfully (Windows batchfiles in my case) to extract coordinate info from photos. Commented Feb 26, 2015 at 20:36
• What platform are you using to parse the information? What are you looking to convert it to? Commented Feb 26, 2015 at 20:38
• I am converting to lat,lng decimal/double values and it was in C#. I simply needed the information that the answer gave. Commented Feb 26, 2015 at 23:47
• In case anyone's wondering why we'd want to do this - so that you can paste the coordinates into google and quickly find out where a point is. Commented Feb 13, 2023 at 22:02

EXIF stores GPS coords as rational64u which is a list of six unsigned whole numbers in the following order:

[
degreesNumerator, degreesDenominator,
minutesNumerator, minutesDenominator,
secondsNumerator, secondsDenominator
]

The format is consistent, and it looks like the tool you are using has already divided each pair into decimal numbers, so what you have is:

Lat: 55°   40.711' 0"
Lng:  8°  30.2282' 0"

If you want to convert to a single decimal number:

= Degrees + Minutes/60 + Seconds/3600
• If you have the raw exif values the denominator has to be taken into account, it's usually 1 for Degrees and Minutes but seems to vary for Seconds: (Degrees = degreesNumerator / degreesDenominator), (Minutes = minutesNumerator / minutesDenominator), (Seconds = secondsNumerator / secondsDenominator), After which the calculation above works just fine.. this one threw me for a loop. Commented Nov 27, 2020 at 5:12

Exiftool will output the coordinates in low precision decimal if you use the -n switch. You can get more precision with -c switch and give the desired quantity of digits behind the decimal:

exiftool -c '%.6f' -GPSPosition filename.jpg

Shows position with 6 digits behind the decimal, which is good for finding a place within 5 inches.

• Note to self: you can still use this even if you're just dumping every property as text with -json and doing the parsing for individual fields with jq. Commented Feb 13, 2023 at 22:01
• > Shows position with 6 digits behind the decimal There is also a blank space and single directional character (N,S,E,W) appended to the floating point number. eg: 31.304792 N. Commented May 10, 2023 at 14:45
• Plain old exiftool -n filename.jpg worked great for me. Per exiftool.org/forum/index.php?topic=3687.0: "You can either use the -n option, which will returns numerical values for all tags, or add a # to an individual tag name (ie. -filesize#) to do this for a single tag." Thanks Billious!
– Ben
Commented Jan 2 at 3:48

According to this page, the latitude and longitude values could be in (1) degrees, (2) degrees and decimal minutes, or (3) degrees, minutes, and decimal seconds.

In your example, (2) is a decimal value and (3) is zero, so you have degrees, decimal minutes.

So, you'll have to some checks on the three values to determine which format is being used.

• According to the exif standard, there are three "rational" fields for each, containing degrees, minutes, and seconds. exiftool normalizes imporoper decimal degrees into D,M,S while assigning these values, (exiftool -GPSLongitude="0.5 90 63.12345" junk.jpg" -> GPS Longitude: 2 deg 1' 3.12" W") So if you need decimal degrees, you do dd=x0+x1/60.+x2/3600. and could ignore the non-normalization. Commented Jan 13, 2016 at 22:17

Improving on Kirt's improvements:

function getExifGpsInfo ($fullname) { 'Fullname: ' +$fullname
$imageProperties =New-Object -TypeName System.Drawing.Bitmap -ArgumentList$fullname
if($imageProperties.PropertyItems|?{($_.id -eq 2) -or ($_.id -eq 4)}){ [double]$LatDegrees = (([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 0)) / ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 4)));
[double]$LatMinutes = ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 8)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 12)); [double]$LatSeconds = ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 16)) / ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 20));
[char]$LatRef = [System.BitConverter]::ToChar($imageProperties.GetPropertyItem(1).Value, 0)
[double]$LonDegrees = (([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 0)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 4))); [double]$LonMinutes = ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 8)) / ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 12));
[double]$LonSeconds = ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 16)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 20)); [char]$LonRef       = [System.BitConverter]::ToChar( $imageProperties.GetPropertyItem(3).Value, 0) "$LatDegrees°$LatMinutes'$LatSeconds.0""$LatRef$LonDegrees°$LonMinutes'$LonSeconds.0""$LonRef" If($LatRef -eq "S") { $LatSign = "-" } else {$LatSign = "" }
If($LonRef -eq "W") {$LonSign = "-" } else { $LonSign = "" }$LatSign + [string]([math]::Round(($LatDegrees +$LatMinutes/60 + $LatSeconds/3600), 7)) + ", " +$LonSign + [string]([math]::Round(($LonDegrees +$LonMinutes/60 + $LonSeconds/3600), 7)) "Latitude:$LatSign$LatDegrees;$LatMinutes; $LatSeconds" "Longitude:$LonSign$LonDegrees;$LonMinutes; $LonSeconds" } } I used this batch file to get file names, date/time and decimal degree positions. **************start lalo.bat '-n forces signed decimal degrees exift -n d:\util\00ymp*.jpg >fud 'strfile one string per line (spaces ok) findstr /G:"strfile" fud >>fum **********end lalo.bat produces output File Name : 0104171345.jpg GPS Date/Time : 2017:01:04 21:45:19Z GPS Position : 46.9997367777778 -117.3392105 File Name : 0104171355.jpg GPS Date/Time : 2017:01:04 21:55:52Z GPS Position : 46.99622725 -117.307495111111 File Name : 0104171402.jpg GPS Date/Time : 2017:01:04 22:02:02Z GPS Position : 47.0075378333333 -117.284553527778 File Name : 0104171404.jpg GPS Date/Time : 2017:01:04 22:04:51Z GPS Position : 47.0222473055556 -117.275527944444 File Name : 0104171405.jpg GPS Date/Time : 2017:01:04 22:05:40Z GPS Position : 47.0269584444444 -117.269523611111 File Name : 0112171921.jpg File Name : 0112171921a.jpg File Name : 0112171921b.jpg File Name : 0120171623.jpg File Name : 0120171623a.jpg File Name : 0120171624.jpg File Name : 0120171626.jpg GPS Date/Time : 2017:01:21 00:26:49Z GPS Position : 48.7900199722222 -117.290061944444 File Name : 0120171628.jpg GPS Date/Time : 2017:01:21 00:28:44Z GPS Position : 48.7907943611111 -117.292045583333 File Name : 0122170942.jpg File Name : 0122170942a.jpg File Name : 0122170948.jpg File Name : 0122170948a.jpg File Name : 0122170950.jpg GPS Date/Time : 2017:01:22 17:50:12Z GPS Position : 48.7828292777778 -117.287322972222 File Name : 0122170950a.jpg GPS Date/Time : 2017:01:22 17:50:16Z GPS Position : 48.7828483333333 -117.287322972222 File Name : 0122170950b.jpg GPS Date/Time : 2017:01:22 17:50:38Z GPS Position : 48.7828178333333 -117.28733825 Thanks Jason for the formula to convert to decimal, and to https://stackoverflow.com/questions/45136895/extracting-gps-numerical-values-from-byte-array-using-powershell function getGPS ($fullname)
{
'Fullname: ' + $fullname$imageProperties =New-Object -TypeName System.Drawing.Bitmap -ArgumentList $fullname if($imageProperties.PropertyItems|?{($_.id -eq 2) -or ($_.id -eq 4)}){
[double]$LatDegrees = (([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 0)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 4))); [double]$LatMinutes = ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 8)) / ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 12));
[double]$LatSeconds = ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 16)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 20)); [double]$LonDegrees = (([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 0)) / ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 4)));
[double]$LonMinutes = ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 8)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 12)); [double]$LonSeconds = ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 16)) / ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 20));
"Latitude: $LatDegrees;$LatMinutes;$LatSeconds" "Longitude:$LonDegrees;$LonMinutes;$LonSeconds"
"DECLatitude: " + ([int]$LatDegrees +($LatMinutes/60) +($LatSeconds/60)) "DECLongitude: " + ([int]$LonDegrees +($LonMinutes/60) +($LonSeconds/60))
}}

getGPS D:\pics\mypic.jpg

Fullname: P:\IMG_0014.JPG Latitude: 42;32.27;0 Longitude: 82;52.58;0 DECLatitude: 42.5378333333333 DECLongitude: 82.8763333333333

• Oh come on, will some bored programmer please make a Javascript page to do this? Paste in the input data, choose options, push a button. Not rocket science. Commented Jun 13, 2022 at 21:25