Photosで選択中の写真をKeynoteの現在の書類の現在のスライド以降に配置 v2
Photosで選択中の写真をKeynoteで現在オープン中の書類の現在のスライド(ページ)以降に配置していくAppleScriptの改良版です。
作業の過程をiPhoneで写真撮影。撮影した写真を写真.app(Photos.app)経由でKeynote書類にまとめる作業を行なっていました。作業工程を時間こみで表示できないとわかりにくかったので、Keynoteの各スライドに時刻を入れるようにAppleScriptを書いておきました。
初版では写真.app(Photos)上の選択項目を一切ソートなどしなかったため、exifから取得した撮影日付で昇順ソートしています。
▲さんかく写真.app(Photos)上でKeynoteに配置したい写真を選択
▲さんかくあらかじめKeynote上でマスタースライド「画像(横長)」上のアイテムを編集しておくといいかも
▲さんかくAppleScriptによって写真.app上の写真をKeynote書類上に順次割り付け。タイトル部分にexifに記録されていた撮影時刻が入る
▲さんかく実行結果。写真.appから割り付けた写真は撮影日時でソートされている
– Created by: Takaaki Naganoya
– Created on: 2019年05月26日
—
– Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use BPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html
use mdLib : script "Metadata Lib" version "2.0.0" –https://www.macosxautomation.com/applescript/apps/Script_Libs.html#Metadata_Lib
property NSUUID : a reference to current application’s NSUUID
property NSString : a reference to current application’s NSString
property SMSForder : a reference to current application’s SMSForder
property NSFileManager : a reference to current application’s NSFileManager
tell application "Keynote"
if (count every document) = 0 then return
end tell
–Photosで選択中の写真をすべて書き出してalias listを取得する
set aList to exportSelectedPhotoOnPhotos() of me
if aList = {} or aList = false then return
set aLen to length of aList
–書き出した画像の親フォルダを求めておく(あとで削除するため)
tell application "Finder"
set parentFol to parent of (item 1 of aList)
end tell
–exifから撮影日時を取得して2D List化
set aaList to {}
repeat with i in aList
set j to contents of i
set exifDate to readExifDateTimeOriginal(j) of me
set the end of aaList to {j, exifDate, (time string of exifDate)}
end repeat
–撮影日時で昇順ソート
set aaaList to sortList2DAscending(aaList, {2}) of me
tell application "Keynote"
tell front document
tell current slide
set curNum to slide number –現在表示中のスライドの番号(ページ数)を取得する
end tell
–Photosから取得した写真のアイテム数でループ
repeat with i from 1 to aLen
copy (item i of aaaList) to {aPhoto, aDateObj, creTime}
set newSlide to make new slide at slide (curNum + i) with properties {base slide:master slide "画像(横長)"} –This item is localized!! Maybe a "Photo"
tell newSlide
set object text of default title item to creTime
set file name of image 1 to aPhoto –place an image to image placeholder
end tell
–配置画像を削除
tell application "Finder"
delete aPhoto –配置した写真を削除
end tell
end repeat
end tell
end tell
–あとしまつ
tell application "Finder"
delete parentFol –画像のダウンロードフォルダを削除
end tell
–Photosで選択中のファイルをtmporaryフォルダに書き出してalias listで返す
on exportSelectedPhotoOnPhotos()
set dtPath to (path to temporary items) as text
set aUUID to NSUUID’s UUID()’s UUIDString() as text
set dirPath to ((POSIX path of dtPath) & aUUID)
set fileManager to NSFileManager’s defaultManager()
set aRes to (fileManager’s createDirectoryAtPath:dirPath withIntermediateDirectories:true attributes:(missing value) |error|:(reference))
set dtPath to dtPath & aUUID
tell application "Photos"
set a to selection
if a = {} then return {}
set aRes to (export a to file dtPath)
end tell
tell application "Finder"
tell folder dtPath
set fList to (every file) as alias list
end tell
end tell
if fList = {} then return false
return fList
end exportSelectedPhotoOnPhotos
–指定JPEG画像のExif情報からDateTimeOriginalを取得してAS dateオブジェクトに変換して返す
on readExifDateTimeOriginal(aTargFileAlias)
set theMetadata to readMetadataFrom(aTargFileAlias) of me
if theMetadata = false then return false
set keysList to theMetadata’s allKeys()
if "{Exif}" is not in (keysList as list) then return false
set exifDate to theMetadata’s valueForKeyPath:"{Exif}.DateTimeOriginal"
if exifDate = missing value then return false
set a to NSString’s stringWithString:exifDate
set {aDateStr, aTimeStr} to (a’s componentsSeparatedByString:" ") as list
set bDateStr to repChar(aDateStr, ":", "/") of me
set fullDate to date (bDateStr & " " & aTimeStr)
return fullDate
end readExifDateTimeOriginal
–指定のファイルからメタデータを取得する
on readMetadataFrom(imageFile)
load framework
set {theRecord, theError} to SMSForder’s metadataFromImage:imageFile |error|:(reference)
if theRecord = missing value then — there was a problem, so extract the error description
error false
else
return theRecord
end if
end readMetadataFrom
–文字置換
on repChar(origText as string, targChar as string, repChar as string)
set curDelim to AppleScript’s text item delimiters
set AppleScript’s text item delimiters to targChar
set tmpList to text items of origText
set AppleScript’s text item delimiters to repChar
set retText to tmpList as string
set AppleScript’s text item delimiters to curDelim
return retText
end repChar
–入れ子のリストを昇順ソート
on sortList2DAscending(a, keyItem)
return sort2DList(a, keyItem, {true}) of me
end sortList2DAscending
–入れ子のリストを降順ソート
on sortList2DDecending(a, keyItem)
return sort2DList(a, keyItem, {false}) of me
end sortList2DDecending
–2D Listをソート
on sort2DList(aList as list, sortIndexes as list, sortOrders as list)
load framework
–index値をAS流(アイテムが1はじまり)からCocoa流(アイテムが0はじまり)に変換
set newIndex to {}
repeat with i in sortIndexes
set j to contents of i
set j to j – 1
set the end of newIndex to j
end repeat
set sortTypes to {}
repeat (length of sortIndexes) times
set the end of sortTypes to "compare:"
end repeat
set resList to (SMSForder’s subarraysIn:(aList) sortedByIndexes:newIndex ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as {missing value, list}
return resList
end sort2DList