[Tutorial] Advanced automation and scripting with AppleScript
2020-09-17 21:25:08
I sent this comment to the support team, but maybe I should post it here instead. I'm new to AppleScript and I think it would be helpful if you had a few photo editing sample scripts. I would like to create a script that takes a folder of Pixelmator Pro files and applies the White Balance and Lightness corrections. I know these commands are in the Pixelmator Pro AppleScript dictionary, but I can't figure out the correct way to script this. If there was a sample of how to use these commands, that could serve as a template for using other commands. Thanks!
0
2020-09-18 06:55:12
Thank you, thank you, THANK YOU for the AppleScript support! I will stay up late experimenting with it. I have a set of steps I take over and over, including a "Trim...", and now I can automate the process. Thank you so much. This is a giant leap upward and forward in terms of being a production tool.
0
2020-09-18 12:16:59
Max, this is a great (perhaps the best) place to ask questions like this! Here's an example script that should do what you're looking for:2020-09-17 18:25:08 I sent this comment to the support team, but maybe I should post it here instead. I'm new to AppleScript and I think it would be helpful if you had a few photo editing sample scripts. I would like to create a script that takes a folder of Pixelmator Pro files and applies the White Balance and Lightness corrections. I know these commands are in the Pixelmator Pro AppleScript dictionary, but I can't figure out the correct way to script this. If there was a sample of how to use these commands, that could serve as a template for using other commands. Thanks!
tell application "Pixelmator Pro"
-- Open a prompt that lets you pick multiple Pixelmator Pro files to process
-- and save references to all those images in the originalImages variable
set originalImages to choose file with prompt ¬
"Please select the images to process:" with multiple selections allowed
-- Start a repeat loop that loops over each image
repeat with a from 1 to number of originalImages
-- Open the current image in the loop
set currentImage to open item a of originalImages
-- Apply the auto white balance adjustments
auto white balance currentImage
-- Apply the auto lightness adjustments
auto light currentImage
-- Export the images to the location chosen previously as Pixelmator Pro files
save currentImage
close currentImage without saving
end repeat
display notification (number of originalImages as text) & ¬
" images have been successfully edited." with title "Auto WB and Auto Lightness"
end tell
And here's a way to script the same thing but export your changes to new documents rather than save them to the ones that were opened:tell application "Pixelmator Pro"
-- Open a prompt that lets you pick multiple Pixelmator Pro files to process
-- and save references to all those images in the originalImages variable
set originalImages to choose file with prompt ¬
"Please select the images to process:" with multiple selections allowed
-- Open a prompt to choose the location where the files should be exported
set exportLocation to choose folder with prompt ¬
"Please select where you'd like export the images:"
-- Start a repeat loop that loops over each image
repeat with a from 1 to number of originalImages
-- Open the current image in the loop
set currentImage to open item a of originalImages
-- Apply the auto white balance adjustments
auto white balance currentImage
-- Apply the auto lightness adjustments
auto light currentImage
-- Export the images to the location chosen previously as Pixelmator Pro files
export currentImage to file ((exportLocation as text) & ¬
name of currentImage & "-edited" & ".pxd") as Pixelmator Pro
-- Close the current image without saving
close currentImage without saving
end repeat
display notification (number of originalImages as text) & ¬
" images have been successfully edited." with title "Auto WB and Auto Lightness"
end tell
Feel free to try out those scripts and let me know how it goes!First of all, welcome to the forum, Christian! Second of all, that's really great to hear. I'll admit that even as a non-programmer, I spent many a fun evening hour tinkering with AppleScript, so I hope you'll enjoy yourself too.2020-09-18 03:55:12 Thank you, thank you, THANK YOU for the AppleScript support! I will stay up late experimenting with it. I have a set of steps I take over and over, including a "Trim...", and now I can automate the process. Thank you so much. This is a giant leap upward and forward in terms of being a production tool.
0
2020-09-18 16:24:49
You're the best! Thanks for these scripts. I'll play around with them this weekend!
0
2020-09-20 12:44:15
Let me suggest a less complicated way to write scripts when they operate on only one layer and all other layers need to be ignored, such as your example script for creating a 3D text effect. Instead of all the work tracking then hiding other visible layers and then restoring their visibility back, copy the current layer into a temporary new document and then bring the results back in. Yes, you would have to create a new document and then close it without saving, but this is only a few statements compared to tracking visible layers, hiding them, and then making them visible again.
0
2020-09-21 09:06:32
Yeah, usually there's no need to remember the visibility of layers even when writing scripts that operate on one layer in a document, but because this particular script uses the merge visible command, it does become necessary. I seem to recall that the merge command cannot take lists in the form of layers 3 thru 12 due to some AppleScript limitations, so I had to use this method. But in most other cases, again, this extra step isn't necessary. I also like your suggestion of creating another document, though I think there might be potential for it to be just as, if not more complex — you'd need to create a new document with the size of the current document, then cut the layer, paste it into the new document, then paste it back in and close the temp document without saving it. So, overall, my feeling is it would about the same, complexity-wise, though possibly with less potential for bugs. Of course, if you'd like to have a go at modifying the script yourself, feel free to do so, I'd love to see it!Let me suggest a less complicated way to write scripts when they operate on only one layer and all other layers need to be ignored, such as your example script for creating a 3D text effect. Instead of all the work tracking then hiding other visible layers and then restoring their visibility back, copy the current layer into a temporary new document and then bring the results back in. Yes, you would have to create a new document and then close it without saving, but this is only a few statements compared to tracking visible layers, hiding them, and then making them visible again.
0
2020-09-22 21:59:14
As an exercise in curiosity I rewrote the 3D Text Effect script to perform its manipulations in a temporary document. Not having to track the working set of layers permits it to be 63 lines shorter, a distinct advantage in my view, so this technique could prove useful for scripts having to do similar layer manipulations. It turns out, creating a document from a copied layer in the clipboard creates a new document with the same attributes, so those didn't have to be specifically carried over. But I did run into an error where changing the color of the text in the temporary document caused it to unexpectedly wrap, damaging the effect. Adding a line to proportionally widen the text layer, either before or after the color change, bypassed the problem. I don't understand this, since the temporary document has the same image, canvas, and text layer properties as the source document, yet setting the text color works fine when done there.
Here is the rewrite:
Here is the rewrite:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
tell application "Pixelmator Pro"
activate
tell front document
if not (count selected layers) = 1 then
display alert "Make sure a single text layer is selected."
return
end if
if not class of current layer = text layer then
display alert "Make sure a single text layer is selected."
return
end if
cut
end tell
make document from clipboard
tell front document
tell layer 1
set fontSize to size of the text content
set width to width + (width * 1.2) -- needed or text wraps when color is set
set color of text content to {65535, 61096, 51260}
convert into shape
end tell
tell styles of layer 1
set stroke width to (fontSize / 25)
set stroke position to center
end tell
tell layer 1
set {coordX, coordY} to position
repeat with stripeThickness from 1 to (fontSize / 18)
duplicate
set the position to {coordX - stripeThickness, coordY - stripeThickness}
end repeat
end tell
set visible of layer 1 to false
merge visible
set visible of layer 1 to true
repeat with currentLayerIndex from 2 to 4
tell layer currentLayerIndex
duplicate
set {coordX, coordY} to position
end tell
set the position of layer (currentLayerIndex + 1) to ¬
{coordX + stripeThickness, coordY + stripeThickness}
end repeat
set numberOfAdditionalStripes to 3
select layer 2
set currentLayerIndex to 2
set rgbCodeList to {{10000, 12543, 23808}, {20736, 44544, 42752}, ¬
{62976, 43776, 23040}, {55552, 22528, 20992}}
set rgbColor to 1
repeat with colorIndex from 1 to (1 + numberOfAdditionalStripes)
set the fill color of the styles of layer currentLayerIndex to ¬
{item rgbColor of rgbCodeList}
set rgbColor to rgbColor + 1
if rgbColor > 4 then
set rgbColor to 1
end if
set currentLayerIndex to currentLayerIndex + 1
end repeat
tell styles of layer 1
set stroke width to 0.0
end tell
merge visible
copy
close saving no
end tell
tell document 1
paste
end tell
end tell
While working on this rewrite I found two errors in Pixelmator Pro's Applescript implemtation: 1) The Dictionary text layer properties for font, size, and text color need to be presented as "get" and not "get/set". Attempting to set these cause a scripting error since setting properties must be done on the object that owns them, even though they can be readable from higher-up objects offering those same properties. 2) The delete command to delete a layer isn't working. Neither of the following work for me:tell application "Pixelmator Pro"
tell document 1
delete current layer -- does nothing
delete item 1 of selected layers -- execution fails
end tell
end
0
2020-09-23 13:31:04
Thanks to Andrius i received this script (below) to convert images to lossless HEIC.
It works fine for JPEGs.
For TIFFs it balks, with the following error:
Tried making the script simply open a file without doing anything, also tried pre-setting source and destination - the same error pops up.
All works for a JPEG, but for a TIFF the script stops after opening the image file in Pixelmator Pro.
Anyone have any idea about what might be happening?
Any tip is greatly appreciated.
cheers
It works fine for JPEGs.
For TIFFs it balks, with the following error:
Ive been on this every time i can for more than a week now and wasnt able to figure it out.error "Can’t make name of missing value into type Unicode text." number -1700 from name of missing value to Unicode text
Tried making the script simply open a file without doing anything, also tried pre-setting source and destination - the same error pops up.
All works for a JPEG, but for a TIFF the script stops after opening the image file in Pixelmator Pro.
Anyone have any idea about what might be happening?
Any tip is greatly appreciated.
cheers
use scripting additions
tell application "Pixelmator Pro"
set originalImages to choose file with prompt "Please select the images to process:" of type {"public.image"} with multiple selections allowed
set exportLocation to choose folder with prompt "Please select where you'd like export the images:"
repeat with a from 1 to number of originalImages
set currentImage to open item a of originalImages
export currentImage to file ((exportLocation as text) & name of currentImage & ".heic") as HEIC with properties {compression factor:100}
close currentImage without saving
end repeat
display notification (number of originalImages as text) & " images exported to HEIC." with title "Export to HEIC"
end tell
0
2020-09-23 14:12:41
Hey there, the script looks to be working fine with TIFFs for me so, if possible, could you share the TIFFs you're trying to process with me at andriusg@pixelmator.com? Here is also fine, if you prefer!
0
2020-09-23 14:28:53
Nice! This looks to also work faster and is more readable, too. Thanks for taking the time to do this!2020-09-22 18:59:14 As an exercise in curiosity I rewrote the 3D Text Effect script to perform its manipulations in a temporary document. Not having to track the working set of layers permits it to be 63 lines shorter, a distinct advantage in my view, so this technique could prove useful for scripts having to do similar layer manipulations.
0
2020-09-23 21:44:23
hey, thx for helping, i wondered about that, but they are all Apple Photos app TIFF exports, hmm.. tiffs are gigantic so sending via we transfer, cheers!2020-09-23 14:12:41 Hey there, the script looks to be working fine with TIFFs for me so, if possible, could you share the TIFFs you're trying to process with me at andriusg@pixelmator.com? Here is also fine, if you prefer!
0
2020-09-24 08:44:31
Thanks for sharing the file, I managed to repro the issue. It looks like it's taking a long time to load the value of the name property and by the time the image is being exported, the value is still missing, resulting in the error. Here's a script that should work in these cases:
use scripting additions
tell application "Pixelmator Pro"
set originalImages to choose file with prompt "Please select the images to process:" of type {"public.image"} with multiple selections allowed
set exportLocation to choose folder with prompt "Please select where you'd like export the images:"
repeat with a from 1 to number of originalImages
set currentImage to open item a of originalImages
set imageName to name of currentImage
export currentImage to file ((exportLocation as text) & imageName & ".heic") as HEIC with properties {compression factor:100}
close currentImage without saving
end repeat
display notification (number of originalImages as text) & " images exported to HEIC." with title "Export to HEIC"
end tell
I've also reported this to the team, we'll look into why this is happening with certain files!
1
2020-09-24 09:33:29
Thank you! Your work with this will save me (& likely many cloud-storage users) countless hours of work and money - my gratitude cannot be overstated.
Something has changed, but an error still pops up, a new one:
Something has changed, but an error still pops up, a new one:
error "Can’t get name of missing value." number -1728 from name of missing value
The highlighted word in the code is again name.
0
2020-09-24 12:00:11
Also, if Pixelmator Pro is having trouble getting the name of those files, let's try a workaround where we set the names using a Finder tell
use scripting additions
tell application "Finder"
set originalImages to choose file with prompt "Please select the images to process:" of type {"public.image"} with multiple selections allowed
set exportLocation to choose folder with prompt "Please select where you'd like export the images:"
set originalImageNames to {}
repeat with a from 1 to number of originalImages
copy name of item a of originalImages to end of originalImageNames
end repeat
end tell
tell application "Pixelmator Pro"
repeat with a from 1 to number of originalImages
set currentImage to open item a of originalImages
set imageName to item a of originalImageNames
export currentImage to file ((exportLocation as text) & imageName & ".heic") as HEIC with properties {compression factor:100}
close currentImage without saving
end repeat
display notification (number of originalImages as text) & " images exported to HEIC." with title "Export to HEIC"
end tell
1
2020-09-24 14:57:47
Same file.. but same with all (Mojave) Photos Exports.
The last script produced the original error:
Was trying to go through this online for similar strangeness, apparently this person had the script working before a system update a loong time ago, but i have changed nothing in the system. Iv been scratching my head a lot with this. But if it works for you maybe we have got a clue? How are you exporting out of Photos tag-wise please?
The last script produced the original error:
error "Pixelmator Pro got an error: Can’t make missing value into type document." number -1700 from missing value to document
https://discussions.apple.com/thread/6732004Was trying to go through this online for similar strangeness, apparently this person had the script working before a system update a loong time ago, but i have changed nothing in the system. Iv been scratching my head a lot with this. But if it works for you maybe we have got a clue? How are you exporting out of Photos tag-wise please?
0
2020-09-25 09:43:15
OK, it looks like TIFF files exported from Photos might just be slow to open and that's what's causing a variety of issues. At least that's what it looks like to me. I was able to repro your error with some larger Photos exports reliably and here's a script that I got to work even with those photos:
use scripting additions
tell application "Finder"
set originalImages to choose file with prompt "Please select the images to process:" of type {"public.image"} with multiple selections allowed
set exportLocation to choose folder with prompt "Please select where you'd like export the images:"
set originalImageNames to {}
repeat with a from 1 to number of originalImages
set extension hidden of item a of originalImages to true
copy displayed name of item a of originalImages to end of originalImageNames
end repeat
end tell
tell application "Pixelmator Pro"
repeat with a from 1 to number of originalImages
set currentImage to open item a of originalImages
if currentImage = missing value then
repeat with repeatCounter from 1 to 10
try
set currentImage to the front document
if currentImage ≠ missing value then
exit repeat
end if
on error
delay 0.5
if repeatCounter = 10 then
activate
display alert "Unable to set currentImage to the front document. Failed at image " & a & " of " & number of originalImages & "."
return
end if
end try
end repeat
end if
set imageName to item a of originalImageNames
export currentImage to file ((exportLocation as text) & imageName & ".heic") as HEIC with properties {compression factor:100}
close currentImage without saving
end repeat
display notification (number of originalImages as text) & " images exported to HEIC." with title "Export to HEIC"
end tell
Fingers crossed it works for you, too! You'll notice in the Pixelmator Pro tell, I try to give currentImage a value a set number of times. If you have some super large images, you can increase the delay or increase the number of attempts before the repeat loop breaks, I just didn't want to end up in an infinite loop just in case something goes wrong.
1
2020-09-25 09:57:37
Hi, I have been on the fence about purchasing Pro (longtime regular Pixelmator customer, though) until I saw this post. I have been wanting this exact functionality forever! As an iOS dev, I've used Pixelmator to create app icons but it was a cumbersome process by hand to resize my 1024x1024 app store image to the smaller sizes (not to mention slightly blurry but I'm not an artist so I do my best.) I jumped into writing this process as a script but it doesn't seem like `export` allows references inside a `tell document` statement?
Here's my attempt:
Here's my attempt:
set desktopPath to (path to desktop as text)
set folderPath to desktopPath & "Exports"
set exportFolder to ""
tell application "Finder"
if exists folder folderPath is false then
make new folder at desktopPath with properties {name:"exports"}
end if
set exportFolder to folder folderPath
end tell
tell application "Pixelmator Pro"
tell its front document
set imageBaseName to (exportFolder as text) & name
# 1024 x 1024
export it to file (imageBaseName & ".png") as PNG with properties {compression factor:100}
set sizes to {180, 167, 152, 120, 76}
repeat with size in sizes
resize image width size height size resolution 72 algorithm ml super resolution
export to file (imageBaseName & "@" & (size as text) & ".png") as PNG with properties {compression factor:100}
undo
end repeat
end tell
end tell
But i get an error
"Pixelmator Pro got an error: Invalid key form." number -10002 from file "Macintosh HD:Users:cool_user:Desktop:exports:SOC Icon.pxd@1024.png" of document 1
0
2020-09-25 11:00:19
Hey Nate, that's partially a (quite weird) syntax issue and partially a (well, quite weird) sandboxing issue. Syntax-wise, if you're inside a document tell block, you should use:
With that in mind, here's a relatively simple way to rewrite your script to get it to work:
export it to (imageBaseName & ".png") as PNG with properties {compression factor:100}
However, this will only work for files that have already been opened by Pixelmator Pro during that session, which means the sandbox allows you to write to those files. If you simply changed your script to remove 'file', you wouldn't get the invalid key form error, but the script would fail silently.With that in mind, here's a relatively simple way to rewrite your script to get it to work:
set desktopPath to (path to desktop as text)
set folderPath to desktopPath & "Exports"
set exportFolder to ""
tell application "Finder"
if exists folder folderPath is false then
make new folder at desktopPath with properties {name:"exports"}
end if
set exportFolder to folder folderPath
end tell
tell application "Pixelmator Pro"
set imageBaseName to (exportFolder as text) & name of the front document
# 1024 x 1024
export the front document to file (imageBaseName & ".png") as PNG with properties {compression factor:100}
set sizes to {180, 167, 152, 120, 76}
repeat with size in sizes
tell the front document to resize image width size height size resolution 72 algorithm ml super resolution
export the front document to file (imageBaseName & "@" & (size as text) & ".png") as PNG with properties {compression factor:100}
tell the front document to undo
end repeat
end tell
0
2020-09-25 11:15:18
Just to loop back, I had to change `undo` to `tell front document to undo` and my base name to `tell front document to set imageName to name` but otherwise, it works! This is so great.
0
2020-09-25 19:50:54
@Andrius Glory Glory.. It Works! i wish you and the Pixelmator team all get many times in hours of joy, the thousand hours you saved me. Can't recommend Pixelmator enough, since the very first versions it has been special and unique, but with this kind of support really nothing compares. Cheers!
0
2020-09-26 15:34:53
Thank you for adding AppleScript support in Pixelmator Pro!
Is there a way to turn fill off completely for a shape layer? I have a shape that only needs a stroke, not a fill.
I have been able to set 'fill opacity' to 0, but would really like to do the equivalent of unchecking the Fill checkbox in the interface.
Thank you!
Is there a way to turn fill off completely for a shape layer? I have a shape that only needs a stroke, not a fill.
I have been able to set 'fill opacity' to 0, but would really like to do the equivalent of unchecking the Fill checkbox in the interface.
Thank you!
0
2020-09-27 17:57:56
This should be easy, but how would you paste at a specific position?
0