Last active
October 29, 2024 18:22
-
-
Save fay59/ca0f77895338245f982b939660218bdc to your computer and use it in GitHub Desktop.
Set GPS coordinates of media items in Photos using GPX file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* | |
To use: | |
1- Launch Photos | |
2- Select photos for which you want to set the GPS location based on a .gpx file | |
3- Adjust date/time of photos (if necessary) | |
4- Launch script, select GPX file, wait | |
*) | |
set tzString to do shell script "date '+%z'" | |
set hoursOffset to (text 1 thru 3 of tzString) as number | |
set minutesOffset to (text 1 thru 1 of tzString) & (text 4 thru 5 of tzString) as number | |
set timeOffset to hoursOffset * 60 + minutesOffset | |
set decimalSeparator to text 2 thru 2 of (0.0 as text) | |
on iso8601(dateString) | |
set resultDate to the current date | |
set the year of resultDate to (text 1 thru 4 of dateString) | |
set the month of resultDate to (text 6 thru 7 of dateString) | |
set the day of resultDate to (text 9 thru 10 of dateString) | |
set the hours of resultDate to (text 12 thru 13 of dateString) | |
set the minutes of resultDate to (text 15 thru 16 of dateString) | |
set the seconds of resultDate to (text 18 thru 19 of dateString) | |
return resultDate + (my timeOffset) * minutes | |
end iso8601 | |
on parseDecimal(decimalString) | |
set oldDelimiters to AppleScript's text item delimiters | |
set AppleScript's text item delimiters to "." | |
set decimalResult to (text item 1 of decimalString & my decimalSeparator & text item 2 of decimalString) as real | |
set AppleScript's text item delimiters to oldDelimiters | |
return decimalResult | |
end parseDecimal | |
on binarySearch(xmlFilePath, photoTime) | |
tell application "System Events" to tell XML element "trk" of XML element "gpx" of XML file xmlFilePath | |
repeat with seg in (every XML element whose name = "trkseg") | |
set lastRecordedTime to my iso8601((value of XML element "time" of last XML element of seg) as string) | |
if photoTime < lastRecordedTime then | |
set trks to every XML element of seg | |
set startIndex to 1 | |
set endIndex to count of trks | |
repeat until startIndex = endIndex | |
set midpoint to startIndex + (endIndex - startIndex) div 2 | |
set midpointTime to my iso8601(value of XML element "time" of item midpoint of trks) | |
if photoTime ≤ midpointTime then | |
set endIndex to midpoint | |
else | |
set startIndex to midpoint + 1 | |
end if | |
end repeat | |
exit repeat | |
end if | |
end repeat | |
tell XML element startIndex of seg | |
set latitude to my parseDecimal(value of XML attribute "lat" as text) | |
set longitude to my parseDecimal(value of XML attribute "lon" as text) | |
set altitude to my parseDecimal(value of XML element "ele" as text) | |
return {latitude, longitude, altitude} | |
end tell | |
end tell | |
end binarySearch | |
tell application "Photos" | |
set photos to (get the selection) | |
set gpxFile to (choose file with prompt "Select a GPX file" of type {"com.apple.dt.document.gpx"}) as string | |
set AppleScript's progress description to "Geotagging photos" | |
set AppleScript's progress total steps to count of photos | |
set AppleScript's progress completed steps to 0 | |
repeat with photo in photos | |
set thisItem to my binarySearch(gpxFile, date of photo) | |
-- No interpolation; assumes that you haven't moved in a while if the time isn't exact. | |
set location of photo to items 1 thru 2 of thisItem | |
-- Apparently, the Photos script defs lie and media items don't have an 'altitude' property. | |
--set altitude of photo to item 3 of thisItem | |
set AppleScript's progress completed steps to (AppleScript's progress completed steps) + 1 | |
end repeat | |
end tell |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
7 years old now, but still very valuable for my needs, GREAT, thank you a lot!
I had to change "com.apple.dt.document.gpx" to "public.xml", though. There were also problems with decimals without ".". A simple if clause eliminates this bug and now I can happily tag my DSLR photos with geotags sampled by iOS app MapOut.