EXIF metadata editor for JPEG images with:
- Python core logic for EXIF and location-history matching
- Legacy PyQt5 desktop GUI (kept as-is)
- New Flutter desktop GUI (dark gray + green glassy theme)
- Added a Flutter macOS app in
flutter_app/ - Added a Python backend API in
flutter_backend.pythat reuses existing logic fromexif.pyandlocation_history.py - Added helper scripts:
scripts/dev-flutter.shfor one-command local startupscripts/build-flutter-macos.shfor release build output
- Python 3.9+ (managed through
uv) - uv
- Flutter SDK (stable)
- macOS desktop target enabled for Flutter
Useful checks:
flutter --version
flutter doctor -vNotes:
- Android SDK is optional unless you want Android builds.
- For signed macOS/iOS distribution builds, install full Xcode (not only Command Line Tools).
uv sync
flutter pub get --project-dir flutter_appOne command starts both Python backend and Flutter desktop app:
./scripts/dev-flutter.shOptional environment overrides:
BACKEND_HOST=127.0.0.1 BACKEND_PORT=8765 ./scripts/dev-flutter.shUse this path when you want to avoid full Xcode for day-to-day UI work.
./scripts/dev-flutter-web.shOptional overrides:
BACKEND_HOST=127.0.0.1 BACKEND_PORT=8765 WEB_DEVICE=chrome ./scripts/dev-flutter-web.shNotes for web mode:
- Folder and location-history file selection use typed absolute paths in the UI.
- Keep backend on
127.0.0.1and run browser on the same machine. - Image previews are served through backend endpoint
/photos/image.
./scripts/build-flutter-macos.shArtifacts are written to:
dist/exif_editor_flutter.appdist/exif_editor_flutter-macos.zip
./scripts/build-flutter-web.shArtifact output:
dist/web/
uv run python edit-exif-cli.py <directory> <latitude> <longitude>Example:
uv run python edit-exif-cli.py ./photos 37.7749 -122.4194uv run python edit-exif-gui.pyRun backend alone:
uv run python flutter_backend.py --host 127.0.0.1 --port 8765Main endpoints include:
/health/photos/list/photos/details/photos/update-gps/photos/update-timezone/photos/update-datetime-offset/location-history/preview/location-history/apply
- GPS coordinates are stored in EXIF as DMS rationals.
- DateTime format is
YYYY:MM:DD HH:MM:SS. - Offset format is
[+-]HH:MM. update_image_gps_exifusespiexif.insertto avoid JPEG re-encode.- Existing PyQt GUI code remains untouched for compatibility.
exif.py- core EXIF functionslocation_history.py- Google Location History matchingedit-exif-cli.py- CLI batch GPS writeredit-exif-gui.py- legacy PyQt5 GUIflutter_backend.py- FastAPI bridge for Flutterflutter_app/- Flutter desktop UIscripts/dev-flutter.sh- local dev launcher (backend + Flutter)scripts/build-flutter-macos.sh- release build helper