I recently transferred all my photos to iPhoto. I share them on Flickr, but I've been unhappy with iPhoto's built-in Flickr support — it has an arbitrary 500 photo limit on web album size, it's crashy, it does weird synchronizations that take ages when combined with lots of large photos and a slow internet connection, it has multiple times failed to send all the full-resolution images — so I've been exploring alternatives. There's at least FlickrExport and Flickr's own Uploadr.
Although the tools work, there's a downside compared to iPhoto's built-in Flickr support. iPhoto has wonderful geotagging support, as does Flickr, but iPhoto doesn't write the data to EXIF tags and that poses a problem for the tools. Uploadr reads just the files and so never sees the data, and apparently iPhoto doesn't provide the data to FlickrExport, either. The result is that Flickr won't know the locations of the photos.
There's a way to work around this problem. The solution is AppleScript. iPhoto exports photo
objects that can tell you their location as set inside iPhoto. The downside to this approach is that it's AppleScript, but apparently the alternatives like Python or JSTalk aren't quite up to tasks like these without application support.
This script will write the locations of the selected photos relies on ExifTool. It will litter your photo directory with files ending with _original
that should contain the unmodified images. You should make sure the modified files are ok before deleting the originals. The usual caveats apply: I'm no AppleScript expert and this has not been tested particularly rigorously. I'd be careful especially if you don't live in the NE hemisphere. And you might want to reduce the number of dialogs. Do what you want with it.
-- This applescript will geotag the selected photos with the
-- location information set in iPhoto.
--
-- You must have exiftool installed; by default it's loaded from
-- /opt/local/bin, where MacPorts installs it from the package
-- p5-image-exiftool.
--
-- Author: Juri Pakaste (http://www.juripakaste.fi/)
--
-- Based on the Set Geo Data.scpt script by
-- Andrew Turner (http://highearthorbit.com)
--
property exifToolOriginal : "_original"
property exifToolPath : "/opt/local/bin/exiftool"
on extract_decimal(realnum)
set res to realnum - (round realnum rounding down)
res
end extract_decimal
on roundFloat(n, precision)
set x to 10 ^ precision
(((n * x) + 0.5) div 1) / x
end roundFloat
on d2s(degs)
log "enter d2s"
if the degs < 0 then
set the degs to degs * -1
end if
set the degrees to round degs rounding down
set the minssecs to extract_decimal(degs)
log "minssecs: " & minssecs
set the minssecs to minssecs * 60
set the mins to round minssecs rounding down
set the minssecs to extract_decimal(minssecs)
log "minssecs 2: " & minssecs
set the secs to minssecs * 60
"" & degrees & "," & mins & "," & roundFloat(secs, 2)
end d2s
on exportCoords(image_file, lat, lng, alt)
set the northSouth to "N"
set the eastWest to "E"
if the lat is less than 0 then
set the northSouth to "S"
set the lat to the lat * -1
end if
if the lng is less than 0 then
set the eastWest to "W"
set the lng to the lng * -1
end if
log "calling d2s on " & lat
set the latstr to my d2s(lat)
set the lngstr to my d2s(lng)
set exifCommand to exifToolPath & " -GPSMapDatum=WGS-84 -gps:GPSLatitude='" & latstr & "' -gps:GPSLatitudeRef='" & northSouth ¬
& "' -gps:GPSLongitude='" & lngstr & "' -gps:GPSLongitudeRef='" & eastWest ¬
& "' -xmp:GPSLatitude='" & latstr & northSouth & "' -xmp:GPSLongitude='" & lngstr & eastWest & "' -xmp:GPSMapDatum='WGS-84'" & " -xmp:GPSVersionID='2.2.0.0'" & " " & quoted form of image_file
display dialog of ("running: " & exifCommand)
set output to do shell script exifCommand
display dialog of output
--do shell script "rm '" & image_file & "'" & exifToolOriginal
end exportCoords
tell application "iPhoto"
activate
try
copy (my selected_images()) to these_images
if these_images is false or (the count of these_images) is 0 then ¬
error "Please select one or more images."
repeat with i from 1 to the count of these_images
set this_photo to item i of these_images
tell this_photo
set the image_file to the image path
set lat to the latitude
set lng to the longitude
set alt to the altitude
end tell
if lat < 90.1 and lng < 180.1 then
my exportCoords(image_file, lat, lng, alt)
else
display alert ("No location set for " & name of this_photo)
end if
log "read image, lat: " & lat & ", lng: " & lng
end repeat
display dialog "Geo Exif write complete."
on error error_message number error_number
if the error_number is not -128 then
display dialog of ("failed on: " & image_file)
display dialog error_message buttons {"Cancel"} default button 1
end if
end try
end tell
on selected_images()
tell application "iPhoto"
try
-- get selection
set these_items to the selection
-- check for single album selected
if the class of item 1 of these_items is album then error
-- return the list of selected photos
return these_items
on error
return false
end try
end tell
end selected_images
Update (2010-02-28): Thank you to @simonmark on Twitter, who pointed out the script had some issues. My version broke if file names had single quotes in them and Simon's version broke with double quotes (admittedly probably rarer in file names.) I was going to leave it as it was, but found the quoted form
method of text
objects in AppleScript Language Guide which, assuming it works correctly, should make the script always work properly (at least in terms of file name handling.) I also copied Simon's better error display code and replaced the extract_decimal
implementation with something that isn't quite as silly as my previous version was.
Update (2010-06-02): I set up a Bitbucket
repository for this
and other scripts I've written for iPhoto.