[Tutorial] Advanced automation and scripting with AppleScript

Discuss and share Pixelmator Pro resources such as templates, mockups, and tutorials.
User avatar

2021-04-07 02:01:54

Andrius - thanks so much!

1 - setting color

here's the code I found to read from Numbers - and this may be overkill because I wasn't sure what exact problem I was having

a - integers not being read as such - thanks for the "as number" guideline for variable assignment

b - RGB colors as a list - example below based on
this
)
c- AppleScript colors are 16 bit - did not realize - How is color handled in AppleScript

		tell application "Numbers" to tell the document "design-inputs" to tell the sheet "design-sheet" to tell table "design-table"
			
			repeat with i from 2 to the count of cells of column "A" -- row 1 is a header so the counter starts at 2
				set DesignName to formatted value of cell i of column "A"
				set SwashText to formatted value of cell i of column "B"
				
				set ListR to formatted value of cell i of column "C"
				set ListG to formatted value of cell i of column "D"
				set ListB to formatted value of cell i of column "E"
				
				set TheFillColor to {} -- this has to be a list and the *257 is needed to convert to 16 bit RGB, which AppleScript requires
				set beginning of TheFillColor to ListR * 257
				set end of TheFillColor to ListG * 257
				set end of TheFillColor to ListB * 257


2 - Rotation - thank you
when I searched the dictionary for "rotate" I only found document-level info and did not notice the *rotation* property for layers...but hoped it would exist. Glad it does.

The possibilities for my personal projects with Pixelmator Pro and AppleScript are endless. I am having fun experimenting.

Thank you for the support you have provided indirectly via all your previous posts and for your thoughtful response to this one!
User avatar

2021-04-07 09:15:02

Ah, just as I suspected! :smiley: You're using "formatted value". If you check the Numbers dictionary, you'll see cell objects have a "value" property, which returns "number, date, text, boolean, or missing value" and a "formatted value" property, which returns text. Simply changing the instances of "formatted value" to "value" wherever you're dealing with numbers should fix this. With that in mind, here's a somewhat optimized way of setting the TheFillColor variable:
repeat with i from 2 to the row count
	set DesignName to formatted value of cell i of column "A"
	set SwashText to formatted value of cell i of column "B"
	set TheFillColor to {}
	repeat with j in {"C", "D", "E"}
		copy ((the value of cell i of column j) as integer) * 257 to the end of TheFillColor
	end repeat
end repeat
My optimizations:

1. Using the "row count" property instead of counting the cells of a particular column.
2. Using a repeat loop to loop through all the cells in columns "C", "D", and "E" and copying each value to the TheFillColor variable.
3. Using "as integer" to turn the real value returned to a more tidy integer value (because we don't need the decimal point).

And finally, you're more than welcome! Tinkering with scripts and making them work is really very fun, so it's my pleasure.
User avatar

2021-04-07 19:09:03

Needless to say, but AppleScript support is very cool!

For my general workflow, I have a single Pixelmator Pro window with multiple tabs. It seems like (and correct me if I'm wrong) the notion of
tell the front document
is unreliable when using tabs. The "front" document seems to be the last document opened, not whichever document tab is currently selected.

I'd like operate on the current document/image, but can't figure out how to access which tab is selected.

Thanks for any help!
User avatar

2021-04-12 15:36:24

by Kurris 2021-04-07 16:09:03 Needless to say, but AppleScript support is very cool!

For my general workflow, I have a single Pixelmator Pro window with multiple tabs. It seems like (and correct me if I'm wrong) the notion of



is unreliable when using tabs. The "front" document seems to be the last document opened, not whichever document tab is currently selected.

I'd like operate on the current document/image, but can't figure out how to access which tab is selected.

Thanks for any help!
To be honest, it should work just as you've said. I've personally never had any issues using it in the way you'd like but if this is easily reproducible, could you create a screen recording of the issue and share it with us at [email protected]? As it does sound like some sort of bug...
User avatar

2021-04-26 20:30:14

Hey Andrius and the Pixelmator Community,
I need some help to automate a "smart erase" use case. Is that possible? I have pictures of products and I'd like to erase the background. The product is always placed in the center and it's quite easy to erase the background with the smart erase tool. Tolerance around 12% is sufficient.
Is it possible to automate following workflow?

open picture
select smart erase and erase from a specific position with tolerance X%
save picture
open next
do the same stuff
...


would be nice if you could help me :blush:
User avatar

2021-04-30 12:17:09

Hi there! Apologies for the late reply, I was a little snowed under with the Pixelmator Pro 2.0.8 release. So, the Smart Erase tool cannot be scripted using the Pixelmator Pro dictionary, but there are workarounds – for example, using a Python script. Here's a script that would do what you're looking for:
tell application "Pixelmator Pro"
	set imagesToProcess to choose file with prompt ¬
		"Please select the images to process:" with multiple selections allowed
	repeat with currentImage in imagesToProcess
		set currentDocument to open currentImage
		tell currentDocument
			tell application "System Events" to tell process "Pixelmator Pro"
				click menu item "Smart Erase" of menu "Tools" of menu bar item "Tools" of menu bar 1
				set {x, y} to position of image 1 of scroll area 1 of the front window
			end tell
			my mouseDrag(x + 1, y + 1, x, y + 31, 1)
		end tell
		tell application "Finder"
			set currentImageLocation to (container of currentImage) as alias
		end tell
		export currentDocument to file (((currentImageLocation) & (name of the front document) & ".png") as text) as PNG
		close currentDocument without saving
	end repeat
	display notification (number of imagesToProcess as text) & ¬
		" images have been successfully processed." with title "Delete Background"
end tell

on mouseDrag(xDown, yDown, xUp, yUp, delayTime)
	-- delayTime because the drag may fail if the UI isn't fast enough without a delay. For what I do, .1 works.
	do shell script "
	
/usr/bin/python <<END


from Quartz.CoreGraphics import CGEventCreateMouseEvent
from Quartz.CoreGraphics import CGEventCreate
from Quartz.CoreGraphics import CGEventPost
from Quartz.CoreGraphics import kCGEventLeftMouseDown
from Quartz.CoreGraphics import kCGEventLeftMouseUp
from Quartz.CoreGraphics import kCGMouseButtonLeft
from Quartz.CoreGraphics import kCGHIDEventTap
from Quartz.CoreGraphics import kCGEventLeftMouseDragged
import time

def mouseEvent(type, posx, posy):

          theEvent = CGEventCreateMouseEvent(None, type, (posx,posy), kCGMouseButtonLeft)

          CGEventPost(kCGHIDEventTap, theEvent)

def mousemove(posx,posy):

          mouseEvent(kCGEventMouseMoved, posx,posy);

def mousedrag(posx,posy):

          mouseEvent(kCGEventLeftMouseDragged, posx,posy);

def mousedown(posxdown,posydown):

          mouseEvent(kCGEventLeftMouseDown, posxdown,posydown);

def mouseup(posxup,posyup):

      mouseEvent(kCGEventLeftMouseUp, posxup,posyup);

ourEvent = CGEventCreate(None);

mousedown(" & xDown & "," & yDown & ");
time.sleep(" & (delayTime as text) & ");
mousedrag(" & xUp & "," & yUp & ");
time.sleep(" & (delayTime as text) & ");
mouseup(" & xUp & "," & yUp & ");

END"
end mouseDrag
The script selects the Smart Erase tool, finds out the coordinates of the image on your screen, and drags from the top left corner of the image down by 30 points (which is 12% tolerance). It can open a number of images in any format and it will export the images to PNG to the same location. Other scripts shared above will let you choose an export location or save to the same image, so feel free to try combining them with this one. Or you can let me know what you need and I can try to script it for you. :sweat_smile:
User avatar

2021-05-01 12:44:44

Thank you Andrius,

it works like a charm :party_face: . I just had to adapt it to my language.
User avatar

2021-05-14 22:35:32

Hello!
I was glad to find out that Pixelmator Pro is helped by Automator and Apple Script but... I am ignorant of both. I would like to do something quite "simple" (not simple for me) and I would appreciate a lot some help.
Since I am creating several pictures that will become a movie, and these pictures are all contained in a folder, I would like to use ML Resize to upscale them.
I have created an extremely simple "app" with Automator, but I can only find the option to upscale by three times. I would like some more freedom, for instance to convert a HD-size frame (1920x1080) to a 4K frame (3840x2160). I am sure it is very simple... but not for me :\
User avatar

2021-05-17 07:49:17

by turbopump 2021-05-14 19:35:32 Hello!
I was glad to find out that Pixelmator Pro is helped by Automator and Apple Script but... I am ignorant of both. I would like to do something quite "simple" (not simple for me) and I would appreciate a lot some help.
Since I am creating several pictures that will become a movie, and these pictures are all contained in a folder, I would like to use ML Resize to upscale them.
I have created an extremely simple "app" with Automator, but I can only find the option to upscale by three times. I would like some more freedom, for instance to convert a HD-size frame (1920x1080) to a 4K frame (3840x2160). I am sure it is very simple... but not for me :\
Hi there! You can do this with both Automator and AppleScript. It's probably easier to do with Automator as you simply need to add a scale images action at the end of your current list of actions. When scaling images to other sizes, ML Super Resolution actually upscale to 3x then, for example, downscales to a smaller size using the standard Bilinear algorithm. So in Automator, you could use the following action sequence:

Ask for Finder Items → Copy Finder Items → Increase Resolution of Images → Scale Images

The first action will let you select the images you'd like to process, then it will copy those to a different location (assuming you'd like to preserve the originals), increase their resolution by 3x, and then scale them down to 3840x2160.

Alternatively, if you'd like to use AppleScript for this, here's what the script would look like:
tell application "Pixelmator Pro"
	set originalImages to choose file with prompt ¬
		"Please select the images to process:" 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
		tell currentImage to resize image width 3840 height 2160 algorithm ml super resolution
		export currentImage to ((exportLocation as text) & name of currentImage & ".jpg") as JPEG with properties {compression factor:100}
		close currentImage without saving
	end repeat
	display notification (number of originalImages as text) & ¬
		" images have been successfully processed." with title "Scale Images"
end tell
User avatar

2021-06-02 08:37:28

Hi Andrius,

I'm hoping you may be able to help me out with a script. On this page, there's a tutorial for frequency separation (viewtopic.php?f=6&t=17286). Would it be possible to create a script to automate this process? Could save a lot of time. I use Pixelmator Pro as a plugin from Apple Photos if that makes any difference.

Thanks!
User avatar

2021-06-02 08:54:11

Hi Yad, Pixelmator Pro now includes a High Pass effect (you'll find it in the Effects tool), so there should no longer be a need to automate this. Have you had a chance to try out that effect?
User avatar

2021-06-07 05:49:34

Hi Andrius, I haven’t. Is there a tutorial about how to use it?
Thank you
User avatar

2021-06-08 11:58:24

Well, there isn't a tutorial about how to use the High Pass effect for retouching, but it would be exactly the same as doing the frequency separation manually and then using that for retouching. You should be able to find tutorials on this on YouTube, even if they're created for other apps – I think they would work for Pixelmator Pro, too.
User avatar

2021-06-08 21:36:02

Is Pixelmator going to have support for shortcuts for Mac? I watched the WWDC keynote yesterday and it looks pretty exciting, I've never created a successful script in Automator, but I've made about 10 scripts in shortcuts for iOS!
User avatar

2021-06-09 08:13:02

by Andrius Well, there isn't a tutorial about how to use the High Pass effect for retouching, but it would be exactly the same as doing the frequency separation manually and then using that for retouching. You should be able to find tutorials on this on YouTube, even if they're created for other apps – I think they would work for Pixelmator Pro, too.
Thank you. I'll try and work it out :)
User avatar

2021-06-09 14:28:52

by Tali 2021-06-08 18:36:02 Is Pixelmator going to have support for shortcuts for Mac? I watched the WWDC keynote yesterday and it looks pretty exciting, I've never created a successful script in Automator, but I've made about 10 scripts in shortcuts for iOS!
Pixelmator Pro will most certainly support Shortcuts – and dare I say that support should be pretty amazing!
User avatar

2021-06-30 15:28:45

Can AS be used to change the exported file name?

Use case:

Mylio, a photo organizing and syncing app, has an image stacking option that will show the edited image instead of the original if is specially named. "_display" is required in front of the .extension, e.g., 2021.06.25-09.37.36.gs.P_display.jpg where "2021.06.25-09.37.36.gs.P.jpg" is the original filename. Of course this can't happen with every export from Pixelmator. I use Keyboard Maestro so could have a shortcut for this case. For example, Cmd-control-E would export with the modified file name and jpg as the file format. I want to be sent to the Save dialog window since the folder might not be the right one.

Mylio has an "Open with" which is how the image would be opened in Pixelmator. The file could be RAW or JPG, but will be saved as JPG. Mylio uses Finder folders and "watches" for any changes in the folders. I probably will save the .pxd of the modified image too. Mylio will ignore it.
User avatar

2021-07-02 15:12:14

by rotamlexiPixelmator 2021-06-30 12:28:45 Can AS be used to change the exported file name?

Use case:

Mylio, a photo organizing and syncing app, has an image stacking option that will show the edited image instead of the original if is specially named. "_display" is required in front of the .extension, e.g., 2021.06.25-09.37.36.gs.P_display.jpg where "2021.06.25-09.37.36.gs.P.jpg" is the original filename. Of course this can't happen with every export from Pixelmator. I use Keyboard Maestro so could have a shortcut for this case. For example, Cmd-control-E would export with the modified file name and jpg as the file format. I want to be sent to the Save dialog window since the folder might not be the right one.

Mylio has an "Open with" which is how the image would be opened in Pixelmator. The file could be RAW or JPG, but will be saved as JPG. Mylio uses Finder folders and "watches" for any changes in the folders. I probably will save the .pxd of the modified image too. Mylio will ignore it.
It sounds to me like this should be possible, although I don't think you can pre-fill text in the save dialog, so it would be easier to let you simply choose the folder and then export to it without you having to enter any file name.

To clarify, does your workflow look like this:

1. You already have an image open that you're editing in Pixelmator Pro
2. You decide you'd like to export this file to jpeg with "_display" in the name but don't know the location will be correct
3. After saving, you don't want to automate anything about your currently open Pixelmator Pro document

If that's correct, your script would look like this:
tell application "Pixelmator Pro"
	set exportLocation to choose folder with prompt "Please select where you'd like export the image:"
	export the front document to file ((exportLocation as text) & name of the front document & "_display" & ".jpg") as JPEG with properties {compression factor:85}
end tell
The only potential roadblock is if you've turned off the "Import images" option in Pixelmator Pro preferences, in which case the extension will be part of the document name and that would need to be handled separately. But let's see if we can get away with a very simple script like this one!
User avatar

2021-07-04 00:10:56

by Andrius 2021-07-02 22:12:14
If that's correct, your script would look like this:



The only potential roadblock is if you've turned off the "Import images" option in Pixelmator Pro preferences, in which case the extension will be part of the document name and that would need to be handled separately. But let's see if we can get away with a very simple script like this one!
Great. Works fine. I now have a Keyboard Maestro macro programmed to Cmd-Shift-E.

I do see a roadblock. If I save in Pixelmator, the .pxd gets added to the name and Mylio doesn't pick it up. But if I turn on "Import images" the file name becomes
IMG_4894.pxd_display.jpg
. So may need to refine this. I probably don't want "Import images" on. I make many quick changes on .jpg's (not usually photos but some scanned documents) and am willing to save over them.

PS: The "Post Reply" Button was mixed in with the text and I didn't see it. Why not a separate button outside the text box?
User avatar

2021-07-05 08:16:37

OK, so sometimes you also want to export PXD files to JPEG, not just JPEG files? In that case, below I've shared a more universal script that should work with any file format. It also won't matter what you've set for the "Import images" option.
tell application "Pixelmator Pro"
	set theFilename to my returnFilenameWithoutExtension(file of the front document as alias)
	set exportLocation to choose folder with prompt "Please select where you'd like export the image:"
	export the front document to file ((exportLocation as text) & theFilename & "_display" & ".jpg") as JPEG with properties {compression factor:85}
end tell

on returnFilenameWithoutExtension(theFile)
	set theFilename to ""
	tell application "Finder"
		if extension hidden of theFile is true then
			set theFilename to displayed name of theFile
		else
			set extension hidden of theFile to true
			set theFilename to displayed name of theFile
			set extension hidden of theFile to false
		end if
	end tell
	return theFilename
end returnFilenameWithoutExtension
by rotamlexiPixelmator PS: The "Post Reply" Button was mixed in with the text and I didn't see it. Why not a separate button outside the text box?
I wish I had a good answer for you that wasn't "it was a design choice". But that's it. That's the answer.

(You absolutely have a point and we'll keep this in mind, though.)
User avatar

2021-07-11 01:00:50

Currently am on the trial with pixelmator and am really glad to be experimenting with the app. Scripting brought me to the app and I’m currently wondering a about a few capabilities.

1) If there is a way to create a shape with the pen to define the points programmatically. Alternatively, I know I could supply SVG.
2) Any examples available for the data reference property.

Seeing how far this can go... and already really impressed.
User avatar

2021-12-21 15:30:33

Do you have any suggestions for creating either a shortcut or script to do the following: Open Pixelmator --> Create a new document from copied image on the clipboard --> And make the background clear (that last step is optional, but would be helpful). If you could point me in the right direction I'd really appreciate it. Thanks!
User avatar

2021-12-21 22:35:54

Are you looking to erase the existing background of the image or to create a new empty layer to serve as the background?
User avatar

2021-12-21 22:43:16

 tell application "Pixelmator Pro"
	activate
	make document from clipboard
end tell
User avatar

2022-02-04 13:59:23

Hi,
It would be very helpfull to be able to rename a Group layer by Applescript, is there any chance this function exists?
And in the same way it would be nice to be able to select a nested layer (by his name) with Applescript or even better to be able to do in with Shortcuts.

Thanks in advance for the answers