A native macOS app for geotagging photos from GPX tracks, designed around the common problem of a camera clock that drifts and a photographer who forgot to re-sync it before the shoot.
exiftool -geotag does a great job matching photo timestamps to GPX
trackpoints, as long as your camera's clock matches your GPS tracker's clock.
When it doesn't, you need to tell it a -geosync offset — but finding the
right offset normally means either taking a deliberate "sync" photo of your
tracker's display (which you forgot to do) or guessing, running exiftool,
eyeballing the result, and iterating.
Geolignment replaces that guess-and-iterate loop with a slider. You see the photos moving along the track in real time as you scrub; when they line up with the features you remember, you're done. Then it runs exiftool for you.
- Live geosync slider. ±12 hours, 1-minute resolution. Pins glide along the track as you scrub — no jumping.
- Persistent GPX library. Point it at one or more folders of
.gpxfiles; they're parsed once and cached on disk (keyed by mtime). Subsequent launches reload instantly. A rescan button forces a full reparse. - Only relevant tracks shown. The map and track list only show the GPX files whose time range actually overlaps your photos — at the current geosync offset. Clicking a track zooms to just the segments that cover your photos (so a file containing multiple unrelated trips doesn't pull the view out to an intercontinental bounding box).
- Per-segment polylines. Multi-
<trkseg>files are drawn as separate lines, so GPS-signal gaps don't appear as phantom straight connectors. - Pin previews. Hover over a pin to see the photo's thumbnail; click to select the photo, which also scrolls the sidebar and shows a larger preview.
- Manual placement for unmatched photos. Select one or more photos in
the sidebar (shift-click for range, cmd-click to toggle), then right-click
anywhere on the map and pick "Place N selected photos here". Placements
are persisted as real GPX files alongside your library
(
Geolignment Manual Placements for YYYY-MM-DD.gpx), so they flow through the same scan/match pipeline and survive restarts. Right-click again to remove them. - Satellite / Hybrid / Standard map styles via the picker in the map's top-right.
- Arrow-key navigation of the photo timeline (↑/← previous, ↓/→ next).
- Live exiftool verification. The exiftool path in Preferences is run
with
-veron launch and on every change; a green "exiftool X.XX detected" or a red error tells you whether writes will succeed.
- macOS 14 (Sonoma) or later
- Xcode 15 or later (to build from source)
- ExifTool installed (Homebrew:
brew install exiftool). The app auto-detects/opt/homebrew/bin/exiftooland/usr/local/bin/exiftool; other paths can be set in the library pane.
git clone <this-repo>
cd Geolignment
xcodebuild -project Geolignment.xcodeproj -scheme Geolignment -configuration Release buildOr open Geolignment.xcodeproj in Xcode and run. The resulting .app goes
in ~/Library/Developer/Xcode/DerivedData/…/Build/Products/.
- Add a GPX folder. In the GPX library pane (top-left), click the
+button and point it at the directory where you keep your tracks. You can add multiple folders. - Select a photo folder. Bottom-left, click "Select Photo Folder…" and
pick a directory of images. JPEG, HEIF, and common RAW formats (CR2, CR3,
NEF, ARW, DNG, and more) are supported. Capture timestamps are read from
EXIF
DateTimeOriginal, interpreted via the camera'sOffsetTimeOriginalif present, otherwise the Mac's current timezone. - Adjust the geosync slider at the bottom of the window. Watch the pins slide along the track. When they land where you remember taking each photo, you're aligned.
- Place any unmatched photos by hand. Shift/cmd-select them in the sidebar, right-click on the map, choose "Place selected photos here".
- Click "Geotag N images" in the bottom-left. Geolignment invokes
exiftool with your geosync offset and all overlapping GPX files,
including any manual-placement files. Original images get their GPS tags
written in place; the
_originalbackups exiftool leaves behind are cleaned up automatically on success.
-
GPX parsing uses Foundation's
XMLParserand captures trackpoint lat/lon/elevation/time plus any<name>inside a<trkpt>(used for photo identity in manual placement files). -
Matching adjusts each photo's
DateTimeOriginalby the current geosync, then binary-searches the bracketing trackpoints within whichever segment covers that time; the coordinate is linearly interpolated between them. Manual-placement tracks sort first so they always win over a simultaneous GPX match. -
Caching. Parsed tracks are persisted to
~/Library/Caches/Geolignment/tracks-cache.plist(binary plist) keyed by absolute path + mtime. Touching a.gpxfile invalidates only that one entry. -
Writing synthesizes a GPX file per date for manual placements (two trkpts bracketing each photo's adjusted time at the chosen lat/lon), then runs:
exiftool -geosync=<offset> -geotag=<real1.gpx> [-geotag=<real2.gpx>…] \ [-geotag=<manual-placements.gpx>] <photo folder>followed by cleaning up
*_originalon success.
- Manual placements are timestamped using your current geosync offset. Changing the offset after placing photos will effectively re-map where those placements point along the track. Remove and re-place if you change your mind about the offset.
- Geolignment writes to the original files (same as
exiftool -geotag … <folder>). Work on a copy if you want a safety net. - RAW format support depends on macOS's installed codecs. If
QuickLookThumbnailingcan generate a preview for it in Finder, Geolignment can too.
See LICENSE file.