Why won't Photoshop revert to earlier history state in script? - applescript

I've written an Applescript to automate watermarking and resizing images for my company. Everything generally works fine — the script saves the initial history state to a variable, resizes the image, adds the appropriate watermark, saves off a jpeg, then reverts to the initial history state for another resize and watermark loop.
The problem is when I try not to use a watermark and only resize by setting the variable wmColor to "None" or "None for all". It seems that after resizing and saving off a jpeg, Photoshop doesn't like it when I try to revert to the initial history state. This is super annoying, since clearly a resize should count as a history step, and I don't want to rewrite the script to implement multiple open/close operations on the original file. Does anyone know what might be going on? This is the line that's generating the problem (it's in both the doBig and doSmall methods, and throws an error every time I ask it just to do an image resize and change current history state:
set current history state of current document to initialState
and here's the whole script:
property type_list : {"JPEG", "TIFF", "PNGf", "8BPS", "BMPf", "GIFf", "PDF ", "PICT"}
property extension_list : {"jpg", "jpeg", "tif", "tiff", "png", "psd", "bmp", "gif", "jp2", "pdf", "pict", "pct", "sgi", "tga"}
property typeIDs_list : {"public.jpeg", "public.tiff", "public.png", "com.adobe.photoshop-image", "com.microsoft.bmp", "com.compuserve.gif", "public.jpeg-2000", "com.adobe.pdf", "com.apple.pict", "com.sgi.sgi-image", "com.truevision.tga-image"}
global myFolder
global wmYN
global wmColor
global nameUse
global rootName
global nameCount
property myFolder : ""
-- This droplet processes files dropped onto the applet
on open these_items
-- FILTER THE DRAGGED-ON ITEMS BY CHECKING THEIR PROPERTIES AGAINST THE LISTS ABOVE
set wmColor to null
set nameCount to 0
set nameUse to null
if myFolder is not "" then
set myFolder to choose folder with prompt "Choose where to put your finished images" default location myFolder -- where you're going to store the jpgs
else
set myFolder to choose folder with prompt "Choose where to put your finished images" default location (path to desktop)
end if
repeat with i from 1 to the count of these_items
set totalFiles to count of these_items
set this_item to item i of these_items
set the item_info to info for this_item without size
if folder of the item_info is true then
process_folder(this_item)
else
try
set this_extension to the name extension of item_info
on error
set this_extension to ""
end try
try
set this_filetype to the file type of item_info
on error
set this_filetype to ""
end try
try
set this_typeID to the type identifier of item_info
on error
set this_typeID to ""
end try
if (folder of the item_info is false) and (alias of the item_info is false) and ((this_filetype is in the type_list) or (this_extension is in the extension_list) or (this_typeID is in typeIDs_list)) then
-- THE ITEM IS AN IMAGE FILE AND CAN BE PROCESSED
process_item(this_item)
end if
end if
end repeat
end open
-- this sub-routine processes folders
on process_folder(this_folder)
set these_items to list folder this_folder without invisibles
repeat with i from 1 to the count of these_items
set this_item to alias ((this_folder as Unicode text) & (item i of these_items))
set the item_info to info for this_item without size
if folder of the item_info is true then
process_folder(this_item)
else
try
set this_extension to the name extension of item_info
on error
set this_extension to ""
end try
try
set this_filetype to the file type of item_info
on error
set this_filetype to ""
end try
try
set this_typeID to the type identifier of item_info
on error
set this_typeID to ""
end try
if (folder of the item_info is false) and (alias of the item_info is false) and ((this_filetype is in the type_list) or (this_extension is in the extension_list) or (this_typeID is in typeIDs_list)) then
-- THE ITEM IS AN IMAGE FILE AND CAN BE PROCESSED
process_item(this_item)
end if
end if
end repeat
end process_folder
-- this sub-routine processes files
on process_item(this_item)
set this_image to this_item as text
tell application id "com.adobe.photoshop"
set saveUnits to ruler units of settings
set display dialogs to never
open file this_image
if wmColor is not in {"None for all", "White for all", "Black for all"} then
set wmColor to choose from list {"None", "None for all", "Black", "Black for all", "White", "White for all"} with prompt "What color should the watermark be?" default items "White for all" without multiple selections allowed and empty selection allowed
end if
if wmColor is false then
error number -128
end if
if nameUse is not "Just increment this for all" then
set nameBox to display dialog "What should I call these things?" default answer ("image") with title "Choose the name stem for your images" buttons {"Cancel", "Just increment this for all", "OK"} default button "Just increment this for all"
set nameUse to button returned of nameBox -- this will determine whether or not to increment stem names
set rootName to text returned of nameBox -- this will be the root part of all of your file names
set currentName to rootName
else
set nameCount to nameCount + 1
set currentName to rootName & (nameCount as text)
end if
set thisDocument to current document
set initialState to current history state of thisDocument
set ruler units of settings to pixel units
end tell
DoSmall(thisDocument, currentName, initialState)
DoBig(thisDocument, currentName, initialState)
tell application id "com.adobe.photoshop"
close thisDocument without saving
set ruler units of settings to saveUnits
end tell
end process_item
to DoSmall(thisDocument, currentName, initialState)
tell application id "com.adobe.photoshop"
set initWidth to width of thisDocument
if initWidth < 640 then
resize image thisDocument width 640 resample method bicubic smoother
else if initWidth > 640 then
resize image thisDocument width 640 resample method bicubic sharper
end if
set myHeight to height of thisDocument
set myWidth to width of thisDocument
if wmColor is in {"White", "White for all"} then
set wmFile to (path to resource "water_250_white.png" in bundle path to me) as text
else if wmColor is in {"Black", "Black for all"} then
set wmFile to (path to resource "water_250_black.png" in bundle path to me) as text
end if
if wmColor is not in {"None", "None for all"} then
open file wmFile
set wmDocument to current document
set wmHeight to height of wmDocument
set wmWidth to width of wmDocument
duplicate current layer of wmDocument to thisDocument
close wmDocument without saving
translate current layer of thisDocument delta x (myWidth - wmWidth - 10) delta y (myHeight - wmHeight - 10)
set opacity of current layer of thisDocument to 20
end if
set myPath to (myFolder as text) & (currentName) & "_640"
set myOptions to {class:JPEG save options, embed color profile:false, quality:12}
save thisDocument as JPEG in file myPath with options myOptions appending lowercase extension
set current history state of current document to initialState
end tell
end DoSmall
to DoBig(thisDocument, currentName, initialState)
tell application id "com.adobe.photoshop"
set initWidth to width of thisDocument
if initWidth < 1020 then
resize image thisDocument width 1020 resample method bicubic smoother
else if initWidth > 1020 then
resize image thisDocument width 1020 resample method bicubic sharper
end if
set myHeight to height of thisDocument
set myWidth to width of thisDocument
if wmColor is in {"White", "White for all"} then
set wmFile to (path to resource "water_400_white.png" in bundle path to me) as text
else if wmColor is in {"Black", "Black for all"} then
set wmFile to (path to resource "water_400_black.png" in bundle path to me) as text
end if
if wmColor is not in {"None", "None for all"} then
open file wmFile
set wmDocument to current document
set wmHeight to height of wmDocument
set wmWidth to width of wmDocument
duplicate current layer of wmDocument to thisDocument
close wmDocument without saving
translate current layer of thisDocument delta x (myWidth - wmWidth - 16) delta y (myHeight - wmHeight - 16)
set opacity of current layer of thisDocument to 20
end if
set myPath to (myFolder as text) & (currentName) & "_1020"
set myOptions to {class:JPEG save options, embed color profile:false, quality:12}
save thisDocument as JPEG in file myPath with options myOptions appending lowercase extension
set current history state of current document to initialState
end tell
end DoBig

If you choose a color : save document "Ducky.tif" as JPEG in file ..... the current document will be document "Ducky.tif".
If you choose "None" or "None for all" : save document "Ducky.tif" as JPEG in file ...... the current document will be document "image_640".
So the variable initialState = history state 2 of document "Ducky.tif" give an error, because this document no longer exists.
To leaving original open, here's a solution , use copying true in your save command.
save thisDocument as JPEG in file myPath with options myOptions appending lowercase extension with copying

Related

macOS Photos and AppleScript: Quicker organization method

The Goal:
In macOS Photos App, highlight/select a bulk of photos, iterate each one.
AppleScript will tell Photos to quickview the photo, ask what 'Album(s)' to add the photo to, then it will ask for a title and caption.
I'm doing this because the 'Info' panel that provides this function doesn't allow for rapid entry, and it's pretty small to work with.
So I suppose I need a couple things:
Show the picture (tell Photos to quick look it)
Identify the 'My Album' folders (eliminate the smart folders from the mix)
Prompt and Update the Title and the Caption (called name and description in the def)
Add the photo to the selected Albums.
I'm not sure if it's just me, but the AppleScript scripting on Photos is just not something I can wrap my head around very well.
Here's what I have so far, but I was hoping you can help.
tell application "Photos"
--Find All Albums
set thefullList to the name of every album of every folder
-- Need:Figure out how to strip Smart Albums out of this query
-- Set comma as the delim to separate the folders/albums
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
set thefullList to every item of thefullList
set AppleScript's text item delimiters to oldDelimiters
-- Test the output (fails to delim, and won't display the string)
display dialog thefullList
-- Clean list of Albums
set albumNames to {thefullList}
-- Get the selected photos from Photos
set theSelection to (get selection)
-- Iterate through each photo
repeat with i in theSelection
-- Tell Photos to 'quick look'
-- Need:(no idea how to make that work yet)
-- Ask the user to choose the Album(s) this photo should go into
set theAlbumChoice to choose from list albumNames with prompt "Where should this photo go?"
-- Tell the Album that this photo is now added
set theAlbum to theAlbumChoice
add i to theAlbum
-- Ask for Title and Caption
display dialog "What's the Title of this Photo?"
set theTitle to text returned of result
display dialog "What's the Caption of this Photo?"
set theCaption to text returned of result
-- Get the Photo ID for adding MetaData
set selectionID to id of item i of theSelection
-- Set the Title and caption
set name of media item id selectionID to theTitle
set description of media item id selectionID to theCaption
end repeat
end tell
property albumNames : {}
property albumIDs : {}
tell application "Photos"
activate
my getAlbumNames(it) -- get all album names and IDs (recursively)
repeat with aPhoto in (get selection) -- process each selected photo
try -- Get the Photo ID
set selectionID to id of aPhoto
on error errorMessage
set ATID to AppleScript's text item delimiters
set AppleScript's text item delimiters to "\""
set selectionID to text item 2 of errorMessage
set AppleScript's text item delimiters to ATID
end try
spotlight media item id selectionID -- Tell Photos to 'quick look'
-- Ask the user to choose the Album(s) this photo should go into
set theAlbumChoice to choose from list albumNames with prompt "Where should this photo go?"
if theAlbumChoice is false then return
-- Find destination folder's ID and add photo to it
repeat with k from 1 to count albumNames
if (item 1 of theAlbumChoice) is (item k of albumNames) then
set theAlbumID to item k of albumIDs
exit repeat
end if
end repeat
add {media item id selectionID} to album id theAlbumID
-- Ask for Title and Caption, and set them
display dialog "What's the Title of this Photo?" default answer ""
set theTitle to text returned of result
display dialog "What's the Caption of this Photo?" default answer ""
set theCaption to text returned of result
set name of media item id selectionID to theTitle
set description of media item id selectionID to theCaption
end repeat
end tell
on getAlbumNames(aFolder) -- recursive handler
tell application "Photos"
set albumNames to albumNames & name of albums of aFolder
set albumIDs to albumIDs & id of albums of aFolder
repeat with subFolder in (get folders of aFolder)
my getAlbumNames(subFolder)
end repeat
end tell
end getAlbumNames

Applescript - ghosted result with applescript set file label

I did make this script in automator.
property unset : 0
property orange : 1
property red : 2
property yellow : 3
property blue : 4
property purple : 5
property green : 6
property grey : 7
property tmplFileName : "__ReadMe" as string
property fileType : ".txt" as string
property labelTag : red
on run {input, parameters}
tell application "Finder"
set currentPath to insertion location as text
-- set filePath to POSIX path of currentPath
set txtfilename to tmplFileName & fileType
set txtFile to make new file at insertion location as alias with properties {name:txtfilename}
set the label index of the item (txtFile as alias) to my labelTag
select txtFile
open txtFile
end tell
return input
end run
It give's me the following result. A ghosted or visible only disabled file.
What do I wrong? This happens only when I set the label. Its about this line
set the label index of the item (txtFile as alias) to my labelTag
Any suggestions? Thank you.
Still don't understand why the file is disabled. Anyway and moving forward, after some reading I came with this as a test script, and it works. Need some error management like check existing file.
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
property |NSURL| : a reference to current application's NSURL
property tmplFileName : "__ReadMe" as string
property fileType : ".txt" as string
property labelTag : "red"
-- Replace tags;
-- setTags - pass a list with new tags and replacing any existing
-- forPath - POSIX path
on setTags:tagList forPath:POSIXPath
set aURL to current application's |NSURL|'s fileURLWithPath:POSIXPath
aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:
on run {input, parameters}
tell application "Finder"
set txtfilename to tmplFileName & fileType
set txtFile to make new file at insertion location as alias with properties {name:txtfilename}
set POSIXPath to POSIX path of (txtFile as text)
(my setTags:{labelTag} forPath:POSIXPath)
select txtFile
tell application "TextEdit"
activate
open txtFile as alias
end tell
end tell
return input
end run
Hope this help some other people as well. Do I get now a plus one vote back from above. As a side note, can some one explain why I did get a -1? just curious.
Thank you.
I took a stab in the dark and thought maybe the problem was the size of the file that was created, was 0 kb's. I decided to add a handler with the write to file command and added a single space as a character to the file. This made the file size 1 byte and then setting the label index worked. I made a few minor adjustments to your initial code, for my purposes but here are the changes I've made and my version of the code.
local unset, orange, red, yellow, blue, purple, green, grey
set {unset, orange, red, yellow, blue, purple, green, grey} to {0, 1, 2, 3, 4, 5, 6, 7}
set tmplFileName to "__ReadMe"
set nameExtension to ".txt"
set labelTag to red
tell application "Finder"
set currentPath to insertion location
set txtfilename to tmplFileName & nameExtension
set txtFile to make new file at insertion location as alias with properties {name:txtfilename, name extension:nameExtension}
my writeToTheFile(txtFile as alias)
set the label index of (txtFile as alias) to labelTag
open txtFile
end tell
on writeToTheFile(txtFile as alias)
set theFile to txtFile as alias
set theText to " "
try
set writeToFile to open for access theFile with write permission
write theText to writeToFile as text starting at eof
close access theFile
on error errMsg number errNum
try
close access theFile
end try
end try
end writeToTheFile

Set a camera in quicktime using applescript

I know there is probably a very simple answer to this. I'm trying to setup an Applescript application that when activated will launch quicktime, open a new movie recording, set the camera and audio, start the recording and then end the recording and save it after 30 seconds.
I currently have a script that is doing everything except setting the camera and audio source. Any tips on how to select a certain camera and audio source using applescript?
Thanks!
Here is the code as it stands now..
--Set some Variables
--Max length of recording
set maxrec to 20 --in seconds
--Ending Message
set EndMsg to "Thank you for participating in this project. Your video has been recorded."
--Begin Loop
repeat
--Get the person's name
repeat
display dialog "What's your name?" default answer ""
set theName to (text returned of result)
if theName ≠ "" then exit repeat
end repeat
--Set the date
set theDate to current date
set y to text -4 thru -1 of ("0000" & (year of theDate))
set m to text -2 thru -1 of ("00" & ((month of theDate) as integer))
set d to text -2 thru -1 of ("00" & (day of theDate))
set h to text -2 thru -1 of ("00" & (hours of theDate))
set mm to text -2 thru -1 of ("00" & (minutes of theDate))
set dateStamp to (y & "-" & m & "-" & d & " " & h & mm as string)
--Create a folder for the person
tell application "Finder"
set p to path to movies folder from user domain
try
make new folder at p with properties {name:"Video Clips"}
end try
set p to (path to movies folder from user domain as text) & "Video Clips:"
make new folder at p with properties {name:dateStamp & " " & theName}
set thePath to result
--Establish the final name of the movie
set fileName to ((thePath as text) & dateStamp & ".mov" as string)
end tell
--Open New Recording, start and stop it
tell application "QuickTime Player"
set newMovieRecording to new movie recording
set windowID to id of first window whose name = "Movie Recording"
delay 2
tell newMovieRecording
--Set Camera to Blackmagic
set current camera of newMovieRecording to Blackmagic of video recording devices
start
end tell
set theSeconds to maxrec
repeat theSeconds times
display dialog theSeconds buttons {} giving up after 1 with title "REMAINING TIME"
set theSeconds to (theSeconds - 1)
end repeat
tell newMovieRecording
stop
end tell
--save and close the recording
set newMovieRecordingDoc to first document whose name = (get name of first window whose id = windowID)
tell newMovieRecordingDoc to save in fileName
set SavedRecordingDoc to first document whose name = (get name of first window whose id = windowID)
tell SavedRecordingDoc to close
quit
end tell
--Display "Thank You" Message
tell application "System Events" to set frontmost of process "Video Booth" to true
display dialog EndMsg giving up after 20 buttons {"Continue…"} ¬
default button 1
end repeat
Here is the error I get right now when I run it.
error "QuickTime Player got an error: Can’t make Blackmagic of every video recording device of document \"Movie Recording\" into type specifier." number -1700 from Blackmagic of every video recording device of document "Movie Recording" to specifier
use the current camera and current microphone properties of your movie recording object. Just replace item 1 with the appropriate device:
set current camera of recording to item 1 of video recording devices
set current microphone of recording to item 1 of audio recording devices
I had accomplished this by doing it manually
tell application "System Events" to tell process "QuickTime Player"
#To open dialog to show available cameras
click button 3 of window 1
#To select our device
click menu item "your_camera_name" of menu 1 of button 3 of window 1
end tell
With this the dialog will open and you will select your camera from the list...
Taken from another answer I made:
https://stackoverflow.com/a/45454785/3685973

I want to set variable once in an applescript droplet but it makes me set it for every file

I wrote an applescript droplet where I would like to:
drag one or more images onto the droplet
3 display dialogs appear asking 'width', 'height', 'format'
process all dropped images using the above text returned of the
3 display dialogs
Currently, the 3 display dialogs appear for each image (e.g. 3 images = 9 dialogs appear). Is there a way I can only answer these dialogs once? Here's my script:
on run
display dialog "This is a droplet"
end run
on open draggedItems
set tid to AppleScript's text item delimiters
--ask for new width
set newWidth to text returned of (display dialog "New Width" default answer ¬
"45" buttons {"Continue…", "Cancel"} ¬
default button 1)
--ask for new height
set newHeight to text returned of (display dialog "New Height" default answer ¬
"45" buttons {"Continue…", "Cancel"} ¬
default button 1)
--ask for formatType
set newFormat to text returned of (display dialog "Image Format" default answer ¬
"jpg" buttons {"Continue…", "Cancel"} ¬
default button 1)
--repeat
repeat with i in draggedItems
set theFile to (i as alias)
set theFilePath to (the POSIX path of theFile)
set fullFileName to name of (info for theFile without size)
set AppleScript's text item delimiters to "."
set fileNameNoExtension to first text item of fullFileName
--set fileExtension to second text item of fullFileName
set AppleScript's text item delimiters to tid
do shell script ("/usr/local/bin/convert " & quoted form of theFilePath & " -resize " & newWidth & "x" & newHeight & "\\! ~/desktop/" & fileNameNoExtension & "." & newFormat)
end repeat
end open
on open draggedItems is already an repeat loop, if you drop 4 files on this droplet
on open draggedItems
display dialog (draggedItems as text)
end open
you will get 4 different dialogs.
You could do something like this
property askingForNew : true
on open draggedItems
if askingForNew is true then
--display dialogs
set askingForNew to false
end if
display dialog (draggedItems as text)
end open
or drag the folder on the droplet and go through the files of it (like this).

AppleScript resize image and save with new name

I'm calling an Applescript from within FilemakerPro.
These are the things I try to achieve:
An image is stored within a container field.
It stores it's name and path in separate fields.
An Applescript is being activated to perform these actions:
It retrieves the data from FilemakerPro
It checks if there is a folder with the same name as the field "calculate_merk_id"
If not, it creates the folder
It creates a new imagefile which name should have "__small" added to his name after it has been resized to 155 x 134, and stores it in this folder
It creates a new imagefile which name should have "__large" added to his name after it has been resized to 400 x 400, and stores it in this folder
The first error I receive is that it cannot retrieve the dimensions of the image. Furthermore, it won't create my resized images ... Anyone who wants to give me a hand in the right direction, please?
set pad to cell "ServerImagePath" of current record
set filenaam to cell "afbeelding_local_vol_pad" of current record
set foldernaam to cell "calculate_merk_id" of current record
set volle_foldernaam to cell "ServerImageFolder" of current record
set volle_filenaam to cell "ServerImageFile" of current record
set target_small_width to 155
set target_small_height to 134
set target_large_width to 400
set target_large_height to 400
tell application "Finder"
if not exists volle_foldernaam then
make new folder at pad with properties {name: foldernaam}
end if
duplicate filenaam to volle_foldernaam with replacing
tell application "Image Events"
launch
set this_image to filenaam
copy dimensions of this_image to {W, H}
if target_small_width is greater than target_small_height then
if W is greater than H then
set the scale_length to (W * target_small_height) / H
set the scale_length to round scale_length rounding as taught in school
else
set the scale_length to target_small_height
end if
else if target_small_height is greater than target_small_width then
if H is greater than W then
set the scale_length to (H * target_small_with) / W
set the scale length to round scale_length rounding as taught in school
else
set the scale_length to target_small_width
end if
else
set the scale_length to target_small_height
end if
scale this_image to size scale_length
pad this_image to dimensions {target_small_width, target_small_height}
save this_image as this_name & "__small"
close this_image
end tell
end tell
You forgot to open the image
set this_image to filenaam
should be
set this_image to open filenaam
Why not do this natively in FileMaker? FM 12 and later have the GetThumbnail() function. A script could calculate a re-sized image into a global field, then export the image from the global field. Completely cross-platform will work on OSX and Windows, even FileMaker Go.
Set Field [ photo_temp_g ; GetThumbnail ( photo_original ; width ; height ) ]
Commit Record/Request []
Export Field Contents [ photo_temp_g ; “<filename>” ]

Resources