Berger Custom Software Ltd.

© Berger Custom Software Ltd. 1999 -

Applescript for Photography

I like the information that is available in the EXIF file that is attached to photos. I started off using iPhoto and then made the transition to Aperture. Both are great programs, but have a few limitations. These scripts helped with some of those limitations, using the wonderful utility EXIFtool by Phil Harvey.

I also did some experimenting with geotagging, and found that some geotagging software would only work with certain GPS file formats. I have included a script that can help simplify your geotagging workflow by automatically converting your track log file to a more usable file format.

Please let me know if you find these scripts useful, or if you have any questions, comments or suggestions.
.

Contents

iPhoto Scripts
Create keywords from EXIF tags
Transfer iPhoto Ratings to Aperture

Aperture Scripts
Get EXIF for Aperture Master Image
Create Aperture tags from EXIF
Export Large and Small JPGs

GPS Scripts
Convert NMEA file to KML and GPX

iPhoto Scripts

Create keywords from EXIF tags

I customised this script to tag photos with keywords corresponding to the lenses that I use on my Nikon D90.
The keywords need to be created in iPhoto before running this script. I was never able to figure out how to create keywords in iPhoto from AppleScript.
	
-- Script Name: Add Tags from EXIF -- Description: This AppleScript will set the tag of the selected photo to the EXIF tags for the Camera Model. -- If the Camera Model is Nikon D90, it will set the tag for the Lens -- Note: You must have keywords set up in iPhoto to match the script -- Author: Lindsay Berger (http://bergersoft.com) -- Date: March 2011 tell application "iPhoto" set myPictures to selection repeat with mypicture in myPictures tell mypicture set the image_file to the image path set the image_title to the title set the image_filename to the image filename end tell select mypicture set myModel to do shell script ¬ "exiftool -s -s -s -Model " & image_file if myModel = "NIKON D90" then assign keyword string "Nikon D90" set myLens to do shell script ¬ "exiftool -s -s -s -Lens " & image_file if myLens = "18-105mm f/3.5-5.6" then assign keyword string "Nikon 18-105mm VR" else if myLens = "70-300mm F/4.5-5.6" then assign keyword string "Nikon 70-300mm VR" else if myLens = "35mm f/1.8" then assign keyword string "Nikon 35mm f/1.8" else if myLens = "11-16mm f/2.8" then assign keyword string "Tokina 11-16mm f/2.8" else if myLens = "17mm F/3.5" then assign keyword string "Tokina 100mm f/2.8" else display dialog "Lens " & myLens & " not found" end if set myPictureControl to do shell script ¬ " exiftool -s -s -s -PictureControlName " & image_file assign keyword string myPictureControl else assign keyword myModel end if end repeat end tell
Back to top

Transfer iPhoto Ratings to Aperture

I made the transition from iPhoto to Aperture. It is easy to import an entire iPhoto library into Aperture, but the import deliberately leaves out the ratings. I had relied on the ratings to guide me to the photos that I wanted to edit in Aperture. Since this amounted to several thousand hotos, I found it inconvenient to redo all of my ratings. This script will copy your ratings from the iPhoto metadata to the Aperture metadata. Both iPhoto and Aperture need to be open. Select the target photos in Aperture. Then select the source photos in iPhoto. The script will loop through the selection in iPhoto. For each photo, it will try to find the photo in the Aperture selection. If it finds it, it will apply the iPhoto rating to Aperture.
	
	
-- Script Name: Transfer iPhoto ratings to Aperture -- Description: This AppleScript will transfer the ratings of selected photos in iPhoto to -- the photos with the same name selected in Aperture. -- -- Author: Lindsay Berger (http://bergersoft.com) -- Date: March 2011 -- tell application "Aperture" set the_main_aperture_selection to selection end tell tell application "iPhoto" set myiPhotoPictures to selection if myiPhotoPictures is {} then display dialog "Please select one or more images in iPhoto" with title "Transfer ratings to Aperture" buttons {"Okay"} return else repeat with mypicture in myiPhotoPictures tell mypicture set the image_title to the title set the iphoto_rating to the rating tell application "Aperture" set cur_aperture_sel to the_main_aperture_selection if cur_aperture_sel is {} then display dialog "Please select one or more target images in Aperture" with title "Create Aperture tags from EXIF" buttons {"Okay"} return else repeat with cur_img in cur_aperture_sel if the name of cur_img is image_title then set the main rating of cur_img to the iphoto_rating exit repeat end if end repeat end if end tell end tell select mypicture end repeat end if end tell
Back to top

Aperture Scripts

Get EXIF for Aperture Master Image

This script displays the full set of EXIF information for the selected master images in Aperture. I use Picture Controls on my Nikon D90, and sometimes like to see which control was used for a certain photo. Nikon puts this information into each photo’s EXIF header, but this information isn’t available in Aperture. The full EXIF is copied to the clipboard when the EXIF is displayed
These scripts are based on scripts I found at fiveyears62.com, Brett Gross Photography , Allan Hise and Bagelturf.
	
-- Script Name: Get EXIF from Aperture Master Image -- Description: This AppleScript will use EXIFtool to get EXIF data for the photos selected in -- Aperture -- It then displays the EXIF in a list dialog, and copies it to the clipboard. -- Pressing OK will advance to the next image. -- -- Author: Lindsay Berger (http://bergersoft.com) -- Date: March 2011 on run set EXIFoutput to return -- leave this blank to get all EXIF data, otherwise specify which fields you want set DesiredEXIFData to "" -- set DesiredEXIFData to "-PictureControlName -LensId, -Flash" tell application "Aperture" set imageSel to (get selection) end tell if imageSel is {} then display dialog "Please select an image in Aperture" with title "EXIF Data" buttons {"Okay"} return else repeat with cur_pic in imageSel set myPath to getPath(cur_pic) set EXIFoutput to EXIFoutput & myPath & return set EXIFoutput to do shell script "exiftool -t " & DesiredEXIFData & " " & myPath set the clipboard to EXIFoutput set EXIFoutput to formatText(EXIFoutput, return) choose from list EXIFoutput with title "List Exif Metadata" with prompt "Picture:" & return & myPath OK button name "OK" cancel button name "Cancel" with empty selection allowed if the result is not {} then -- OK was pressed. Keep going through the images if the result is false then -- cancel was pressed exit repeat end if end if end repeat end if end run on getPath(aItem) tell application "Aperture" tell library 1 tell aItem set MasterFile to (get value of other tag "FileName") set isReferenced to get referenced if isReferenced then set FinderPath to choose file MasterFile with prompt "Please locate referenced file" set thePath to POSIX path of FinderPath else set ImpGroup to (get value of other tag "ImportGroup") set MasterPath to my GetMasterPath(ImpGroup) set MasterPath to my getLibPath() & MasterPath set thePath to quoted form of (MasterPath & MasterFile) end if end tell end tell end tell return thePath end getPath on GetMasterPath(aStr) set tid to AppleScript's text item delimiters set AppleScript's text item delimiters to "-" set aYear to text item 1 of aStr set aMonth to text item 2 of aStr set aRest to text item 3 of aStr set AppleScript's text item delimiters to " @ " set aDay to text item 1 of aRest set aRest to text item 2 of aRest set AppleScript's text item delimiters to ":" set anHour to text item 1 of aRest set aMinute to text item 2 of aRest set aRest to text item 3 of aRest set AppleScript's text item delimiters to " " set aSecond to text item 1 of aRest set AmPm to text item 2 of aRest if AmPm is equal to "PM" then set anHour to anHour + 12 end if set AppleScript's text item delimiters to "/" set aRest to {"", "Masters", aYear, aMonth, aDay, aYear & aMonth & aDay & "-" & anHour & aMinute & aSecond, ""} as text set AppleScript's text item delimiters to tid return aRest end GetMasterPath on getLibPath() tell application "System Events" to set p_libPath to value of property list item "LibraryPath" of property list file ((path to preferences as Unicode text) & "com.apple.aperture.plist") if ((offset of "~" in p_libPath) is not 0) then set p_script to "/bin/echo $HOME" set p_homePath to (do shell script p_script) set p_offset to offset of "~" in p_libPath set p_path to text (p_offset + 1) thru -1 of p_libPath set g_libPath to p_homePath & p_path return g_libPath else return p_libPath end if end getLibPath on formatText(aStr, aDelimiter) set oldDelimiters to AppleScript's text item delimiters set AppleScript's text item delimiters to aDelimiter set theArray to every text item of aStr set AppleScript's text item delimiters to oldDelimiters return theArray end formatText
Back to top

Create Aperture tags from EXIF

This script will use EXIFtool to get any available EXIF data for the photos selected in Aperture. It then creates a custom tag for the specified field and sets the value to the value for that field
	
-- Script Name: Create Aperture Tags from EXIF -- Description: This AppleScript will use EXIFtool to get any available EXIF data for the photos -- selected in Aperture -- It then creates a custom tag for the specified field and sets the value of the tag to the value -- of the EXIF field -- -- Author: Lindsay Berger (http://bergersoft.com) -- Date: March 2011 -- on run -- put in a list of desired fields to convert to tags. -- e.g. set DesiredEXIFData to "-PictureControlName -Flash -LensId" etc. -- An empty string will give you ALL values set DesiredEXIFData to "-PictureControlName" tell application "Aperture" set imageSel to selection end tell if imageSel is {} then display dialog "Please select an image in Aperture" with title "Create Aperture tags from EXIF" buttons {"Okay"} return else set oldDelimiters to AppleScript's text item delimiters set AppleScript's text item delimiters to tab repeat with i from 1 to count of imageSel set myPath to getPath(item i of imageSel) set EXIFoutput to do shell script "exiftool -t " & DesiredEXIFData & " " & myPath set EXIFoutput to the paragraphs of EXIFoutput repeat with fields in EXIFoutput set fields to fields's text items set MetadataField to item 1 of fields set MetadataValue to item 2 of fields tell application "Aperture" tell library 1 tell item i of imageSel make new custom tag with properties {name:MetadataField, value:MetadataValue} end tell end tell end tell end repeat end repeat set AppleScript's text item delimiters to oldDelimiters end if end run on getPath(aItem) -- get the path for the current photo tell application "Aperture" tell library 1 tell aItem set ImpGroup to (get value of other tag "ImportGroup") set MasterPath to my GetMasterPath(ImpGroup) set MasterFile to (get value of other tag "FileName") end tell end tell end tell set MasterPath to my getLibPath() & MasterPath set thePath to quoted form of (MasterPath & MasterFile) return thePath end getPath on GetMasterPath(aStr) set tid to AppleScript's text item delimiters set AppleScript's text item delimiters to "-" set aYear to text item 1 of aStr set aMonth to text item 2 of aStr set aRest to text item 3 of aStr set AppleScript's text item delimiters to " @ " set aDay to text item 1 of aRest set aRest to text item 2 of aRest set AppleScript's text item delimiters to ":" set anHour to text item 1 of aRest set aMinute to text item 2 of aRest set aRest to text item 3 of aRest set AppleScript's text item delimiters to " " set aSecond to text item 1 of aRest set AmPm to text item 2 of aRest if AmPm is equal to "PM" then set anHour to anHour + 12 end if set AppleScript's text item delimiters to "/" set aRest to {"", "Masters", aYear, aMonth, aDay, aYear & aMonth & aDay & "-" & anHour & aMinute & aSecond, ""} as text set AppleScript's text item delimiters to tid return aRest end GetMasterPath on getLibPath() tell application "System Events" to set p_libPath to value of property list item "LibraryPath" of property list file ((path to preferences as Unicode text) & "com.apple.aperture.plist") if ((offset of "~" in p_libPath) is not 0) then set p_script to "/bin/echo $HOME" set p_homePath to (do shell script p_script) set p_offset to offset of "~" in p_libPath set p_path to text (p_offset + 1) thru -1 of p_libPath set g_libPath to p_homePath & p_path return g_libPath else return p_libPath end if end getLibPath
Back to top

Export Large and Small JPGs

This script will export large and small versions of the selected versions. It prompts for a directory, and creates it if it does not exist. It creates two subdirectores, and exports large JPGs to one and small JPGs to the other. You can use the export settings of your choice and add directories for additional export options.
	
-- Script Name: Export Large and Small JPGs -- Description: This AppleScript will export large and small versions of selected photos to a folder that you specify -- You can use the folder as a staging folder for burning a disc -- Author: Lindsay Berger (http://bergersoft.com) -- Date: June 2012 -- tell application "Finder" -- Prompt for top level folder set exportDir to (choose folder with prompt "Choose a folder for export") as alias -- Check if folder already has "Small Files" and "Large Files" sub folders, if not, create them. if not (exists folder "Small Files" of exportDir) then make new folder at exportDir with properties {name:"Small Files"} end if if not (exists folder "Large Files" of exportDir) then make new folder at exportDir with properties {name:"Large Files"} end if -- Assign references to the subfolders for be used by Aperture set exportDirSmall to (exportDir as text) & "Small Files" as alias set exportDirLarge to (exportDir as text) & "Large Files" as alias end tell -- Tell Aperture to export selected images as JPEGs. tell application "Aperture" activate set imageSel to (get selection) if imageSel is {} then error "Please select image(s) before exporting." else set exportDir to exportDirSmall export imageSel using export setting "JPEG - Fit within 1024 x 1024" to exportDir metadata embedded set exportDir to exportDirLarge export imageSel using export setting "JPEG - Original Size 300 DPI" to exportDir metadata embedded end if end tell
Back to top

GPS Scripts

Convert NMEA file to KML and GPX

This script uses GPSBabel to convert GPS files to these other formats. It is set up to work as a folder action, so you can just drag your GPS files into a folder and have them automatically converted. It creates subfolders to separate the original file, the GPX file, and the KML file.
	
(* convert - NMEA to KML and GPX This Folder Action handler is triggered whenever items are added to the attached folder. The script convert files from NMEA Sentences to KML (Google Earth) and GPX. Copyright © 2002–2007 Apple Inc. You may incorporate this Apple sample code into your program(s) without restriction. This Apple sample code has been provided "AS IS" and the responsibility for its operation is yours. You are not permitted to redistribute this Apple sample code as "Apple sample code" after having made changes. If you're going to redistribute the code, we require that you make it clear that the code was descended from Apple sample code, but that you've made changes. Modified from Apple's Convert PSD to PDF *) property kml_done_foldername : "KML" property gpx_done_foldername : "GPX" property originals_foldername : "NMEA" property newfile_extension : "txt" property kml_extension : "kml" property gpx_extension : "gpx" property input_format : "nmea" property kml_format : "kml" property gpx_format : "gpx" -- since file types are optional in Mac OS X, -- check the name extension if there is no file type -- NOTE: do not use periods (.) with the items in the name extensions list -- eg: {"txt", "text", "jpg", "jpeg"}, NOT: {".txt", ".text", ".jpg", ".jpeg"} property extension_list : {"txt", "TXT", "log", "LOG"} on adding folder items to this_folder after receiving these_items tell application "Finder" if not (exists folder kml_done_foldername of this_folder) then make new folder at this_folder with properties {name:kml_done_foldername} end if set the kml_results_folder to (folder kml_done_foldername of this_folder) as alias if not (exists folder gpx_done_foldername of this_folder) then make new folder at this_folder with properties {name:gpx_done_foldername} end if set the gpx_results_folder to (folder gpx_done_foldername of this_folder) as alias if not (exists folder originals_foldername of this_folder) then make new folder at this_folder with properties {name:originals_foldername} set current view of container window of this_folder to list view end if set the originals_folder to folder originals_foldername of this_folder end tell try repeat with i from 1 to number of items in these_items set this_item to item i of these_items set the item_info to the info for this_item if (the name extension of the item_info is in the extension_list) then tell application "Finder" my resolve_conflicts(this_item, originals_folder, "") set the kml_file_name to my resolve_conflicts(this_item, kml_results_folder, kml_extension) set the gpx_file_name to my resolve_conflicts(this_item, gpx_results_folder, gpx_extension) set the source_file to (move this_item to the originals_folder with replacing) as alias end tell process_item(source_file, kml_format, kml_file_name, kml_results_folder) process_item(source_file, gpx_format, gpx_file_name, gpx_results_folder) end if end repeat on error error_message number error_number if the error_number is not -128 then tell application "Finder" activate display dialog error_message buttons {"Cancel"} default button 1 giving up after 120 end tell end if end try end adding folder items to on resolve_conflicts(this_item, target_folder, new_extension) tell application "Finder" set the file_name to the name of this_item set file_extension to the name extension of this_item if the file_extension is "" then set the trimmed_name to the file_name else set the trimmed_name to text 1 thru -((length of file_extension) + 2) of the file_name end if if the new_extension is "" then set target_name to file_name set target_extension to file_extension else set target_extension to new_extension set target_name to (the trimmed_name & "." & target_extension) as string end if if (exists document file target_name of target_folder) then set the name_increment to 1 repeat set the new_name to (the trimmed_name & "." & (name_increment as string) & "." & target_extension) as string if not (exists document file new_name of the target_folder) then -- rename to conflicting file set the name of document file target_name of the target_folder to the new_name exit repeat else set the name_increment to the name_increment + 1 end if end repeat end if end tell return the target_name end resolve_conflicts -- this sub-routine processes files on process_item(source_file, output_format, new_name, results_folder) -- NOTE that the variable this_item is a file reference in alias format -- FILE PROCESSING STATEMENTS GO HERE try set the source_item to the quoted form of the POSIX path of the source_file -- the target path is the destination folder and the new file name set the target_path to the quoted form of the POSIX path of (((results_folder as string) & new_name) as string) with timeout of 900 seconds do shell script "'/Applications/GPS Applications/'gpsbabel -i " & input_format & " -f " & source_item & " -o " & output_format & " -F " & target_path end timeout on error error_message tell application "Finder" activate display dialog error_message buttons {"Cancel"} default button 1 giving up after 120 end tell end try end process_item
Back to top