[Tutorial] Advanced automation and scripting with AppleScript

Discuss Pixelmator Pro tutorials and share useful resources.
User avatar

2021-02-03 15:52:48

This is so great! Thank you!
User avatar

2021-02-04 19:43:26

Forgive me for my ignorance, but I'm trying to come up with a simple AppleScript that will simply batch open a folder of images, scale them to a certain resolution, and then save them at 100% quality. I've done tons of searches but not found what I'm looking for. I made an automator quick action in finder to scale them which works but it seems to save them at a low to medium quality which doesn't work for me. I want full 100% quality. What is the easiest way to get this? Thanks so much for any help! Currently, I've been opening each file in Pixelmator Pro and doing canvas size, changing resolution, then export and choosing 100% quality.
User avatar

2021-02-05 09:26:55

Hi Kris, it sounds like creating an AppleScript for this should be quite easy, but in order for me to get a better idea of what you're looking for, could you let me know what size images you're starting with and what exactly you do in Pixelmator Pro?
User avatar

2021-02-05 16:28:40

by Andrius 2021-02-05 17:26:55 Hi Kris, it sounds like creating an AppleScript for this should be quite easy, but in order for me to get a better idea of what you're looking for, could you let me know what size images you're starting with and what exactly you do in Pixelmator Pro?
Surely! I'm starting with some 2880x1800 HEIC images, and I'm changing the resolution to be 2388x1688 (iPad Pro 11" resolution) so that these can be used in shortcuts to be set as wallpaper automatically. The great guys who make 24 Hour Wallpaper for macOS got me going on this. I'm saving them still as HEIC files at 100% quality, just at the lower resolution. I'm also forcing that resolution and not using the relative option. Does this make sense?

I should add, I'm also going with the default center selection of the image and not moving the selection either way. I'm doing this from Image, Canvas size menu in Pixelmator Pro.
User avatar

2021-02-12 15:47:47

Hi. Thanks again for all the help. Is it possible to create an AppleScript that would take a folder of pxd files and turn them into jpegs at a quality that I set (say 95%)? I have the automator script that does this, but I'm unable to set the quality level. Thanks!
User avatar

2021-02-19 08:03:06

Okay, by copying some other scripts and making a few changes, I came up with this script that takes a group of Pixelmator files and turns them into jpegs. It also allows the user to set the compression level. The only problem I'm having is that it renames the new files with the pxd suffix included. For example file IMG_023.pxd is turned into IMG_023.pxd.jpeg instead of just IMG_023.jpeg. Any thoughts on how to fix this?
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
		export currentImage to file ((exportLocation as text) & name of currentImage & ".jpg") as JPEG with properties {compression factor:95}
		close currentImage without saving
	end repeat
	display notification (number of originalImages as text) & " images exported to JPEG." with title "Export to JPEG"
end tell
User avatar

2021-02-19 11:08:03

by Kris Venden 2021-02-05 14:28:40 Surely! I'm starting with some 2880x1800 HEIC images, and I'm changing the resolution to be 2388x1688 (iPad Pro 11" resolution) so that these can be used in shortcuts to be set as wallpaper automatically. The great guys who make 24 Hour Wallpaper for macOS got me going on this. I'm saving them still as HEIC files at 100% quality, just at the lower resolution. I'm also forcing that resolution and not using the relative option. Does this make sense?

I should add, I'm also going with the default center selection of the image and not moving the selection either way. I'm doing this from Image, Canvas size menu in Pixelmator Pro.
Hi Kris, I've only just got around to this, my bad! Here's what that 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 filenamesWithoutExtensions to my removeExtensions(originalImages)
	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 currentFilename to item a of filenamesWithoutExtensions
		resize canvas of currentImage width 2388 height 1688 anchor position middle center
		export currentImage to file ((exportLocation as text) & ¬
			currentFilename & "-resized" & ".heic") as HEIC 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 "Resize Canvas and Export to HEIC"
end tell

on removeExtensions(listOfFiles)
	set filenames to {}
	tell application "Finder"
		repeat with currentFile in listOfFiles
			if extension hidden of currentFile is true then
				copy displayed name of currentFile to end of filenames
			else
				set extension hidden of currentFile to true
				copy displayed name of currentFile to end of filenames
				set extension hidden of currentFile to false
			end if
		end repeat
	end tell
	return filenames
end removeExtensions
Max, the handler in the script above should also do the job for you. Let me know if you need any help with incorporating it into your script!
User avatar

2021-02-19 15:16:10

Thanks for the reply!

Yes, I do need help incorporating that into my script. I really only know how to take existing scripts and adapt them Is there a better script to do what I'm trying to do? I also want to make sure that the script is correctly naming the files and not resaving the jpegs a 2nd time with a new name.
User avatar

2021-02-19 15:44:11

Looking at your script, it seems to be just about the right one for what you're looking to do. Just to clarify:

1. You have a folder of PXD files
2. You'd like to export them to JPEG to a different location at 95% quality
3. The files have the PXD extension, so you want to remove this from the filename in the exported versions

If so, the following should work:
tell application "Pixelmator Pro"
	set originalImages to choose file with prompt "Please select the images to process:" with multiple selections allowed
	set filenamesWithoutExtensions to my removeExtensions(originalImages)
	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 currentFilename to item a of filenamesWithoutExtensions
		export currentImage to file ((exportLocation as text) & currentFilename & ".jpg") as JPEG with properties {compression factor:95}
		close currentImage without saving
	end repeat
	display notification (number of originalImages as text) & " images exported to JPEG." with title "Export to JPEG"
end tell

on removeExtensions(listOfFiles)
	set filenames to {}
	tell application "Finder"
		repeat with currentFile in listOfFiles
			if extension hidden of currentFile is true then
				copy displayed name of currentFile to end of filenames
			else
				set extension hidden of currentFile to true
				copy displayed name of currentFile to end of filenames
				set extension hidden of currentFile to false
			end if
		end repeat
	end tell
	return filenames
end removeExtensions
Hope that helps!
User avatar

2021-02-19 16:25:23

by Andrius 2021-02-19 19:08:03
Hi Kris, I've only just got around to this, my bad! Here's what that script would look like:
Thanks so much, Andrius!!
User avatar

2021-02-19 17:07:30

Thanks! I'll give it a try.
User avatar

2021-02-19 18:31:23

by Andrius 2021-02-19 19:08:03
Hi Kris, I've only just got around to this, my bad! Here's what that script would look like:
One last question, Andrius. If I wanted it to overwrite the existing file, rather than save as a new filename, would that be an easy change to make in the code? Thanks again!
User avatar

2021-02-20 13:36:00

by Kris Venden
One last question, Andrius. If I wanted it to overwrite the existing file, rather than save as a new filename, would that be an easy change to make in the code? Thanks again!
It would actually be a much simpler script. Not needing to worry about getting the filenames of the original files and removing the extensions cuts it by quite a few lines. Here's the script:
tell application "Pixelmator Pro"
	set originalImages to choose file with prompt ¬
		"Please select the images to process:" with multiple selections allowed
	repeat with a from 1 to number of originalImages
		set currentImage to open item a of originalImages
		resize canvas of currentImage width 2388 height 1688 anchor position middle center
		export currentImage to file (item a of originalImages) as HEIC 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 "Resize Canvas and Export to HEIC"
end tell
User avatar

2021-02-20 17:26:14

by Andrius 2021-02-20 21:36:00
It would actually be a much simpler script. Not needing to worry about getting the filenames of the original files and removing the extensions cuts it by quite a few lines. Here's the script:
This is great! Thanks so much again, for your help. You're saving me SO much time with this!
User avatar

2021-03-17 22:30:19

Andrius per your script for bulk HEIC conversion, I made a couple of additions:

- Prompt the user for a folder location for lossless export (quality 100)
- Prompt the user for a folder location for lossy export for smartphone / web use (quality 80)
- increase repeatcounter to 30 (loading files over network introduced some delay)
- implement progress bar
use scripting additions

set originalImages to choose file with prompt "Please select the images to process:" of type {"public.image"} with multiple selections allowed
set exportLosslessLocation to choose folder with prompt "Please select where you'd like export the Lossless images:"
set exportLossyLocation to choose folder with prompt "Please select where you'd like export the Lossy images:"
set originalImageNames to {}

set imageCount to number of originalImages
set progress total steps to imageCount
set progress completed steps to 0
set progress description to "Preparing Images..."
set progress additional description to "Preparing to process."

repeat with a from 1 to imageCount
	set progress additional description to "Preparing image " & a & " of " & imageCount
	tell application "Finder"
		set extension hidden of item a of originalImages to true
		copy displayed name of item a of originalImages to end of originalImageNames
	end tell
	set progress completed steps to a
end repeat

set progress completed steps to 0
set progress description to "Processing Images..."
set progress additional description to "Preparing to process."

repeat with a from 1 to imageCount
	set progress additional description to "Processing image " & a & " of " & imageCount
	tell application "Pixelmator Pro"
		set currentImage to open item a of originalImages
		if currentImage = missing value then
			repeat with repeatCounter from 1 to 30
				try
					set currentImage to the front document
					if currentImage ≠ missing value then
						exit repeat
					end if
				on error
					delay 0.5
					if repeatCounter = 30 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 ((exportLosslessLocation as text) & imageName & ".heic") as HEIC with properties {compression factor:100}
		export currentImage to file ((exportLossyLocation as text) & imageName & ".heic") as HEIC with properties {compression factor:80}
		close currentImage without saving
	end tell
	set progress completed steps to a
end repeat

display notification (imageCount as text) & " images exported to HEIC." with title "Export to HEIC"
set progress total steps to 0
set progress completed steps to 0
set progress description to ""
set progress additional description to ""
User avatar

2021-03-18 10:27:39

by Joel McCotter 2021-03-17 20:30:19 Andrius per your script for bulk HEIC conversion, I made a couple of additions:

- Prompt the user for a folder location for lossless export (quality 100)
- Prompt the user for a folder location for lossy export for smartphone / web use (quality 80)
- increase repeatcounter to 30 (loading files over network introduced some delay)
- implement progress bar
Hi Joel, nice! I'm always happy to see people working on scripts.

One thing, though – I think the if clause (that checks whether currentDocument is a missing value) should no longer be necessary because we added a fix to our AS implementation that should, in theory, wait until the document has been fully opened before assigning the variable and moving on to the next part of the script. Is that not working with network files?
User avatar

2021-03-18 15:01:36

Thank you for all the scripts you've created for me. It's really helped my workflow.

I've got a new question for you. Sometimes there are groups of images that the ML adjustments for auto white balance and auto light are too strong. Is there a way to change the opacity of the the layer so that only 50% of the correction is applied? Here's the original script you created for me.
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
		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
		auto white balance currentImage
		auto light currentImage
		tell the color adjustments of layer 1 of currentImage
			set its sharpen to 150
			set its sharpen radius to 1
		end tell
		export currentImage to file ((exportLocation as text) & ¬
			name of currentImage & ".pxd") as Pixelmator Pro
		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
User avatar

2021-03-18 16:03:01

Sure, something like this should work:
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 layer 1 of currentImage
			tell its color adjustments
				set its sharpen to 150
				set its sharpen radius to 1
			end tell
			duplicate
			auto white balance
			auto light
			set opacity to 50
		end tell
		export currentImage to file ((exportLocation as text) & ¬
			name of currentImage & ".pxd") as Pixelmator Pro
		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
Note, I sharpen the layer before duplicating because if only the top layer was sharpened, only 50% of the sharpening would be applied and I guess you don't want that. I also removed that if clause to clean up the script – but do let me know if you ever get that missing value error again.
User avatar

2021-03-18 17:33:49

Yes, sharpening before is perfect. Thanks! I'll give it a try.
User avatar

2021-03-18 17:42:42

For some reason, it does the first file of a folder of images and then stops.
User avatar

2021-03-19 08:10:10

Err, whoops! I was debugging and left a "return" in there, which stops the script. I removed it from my original comment and it should work now.
User avatar

2021-03-19 15:29:08

It works great now, thank you. I just tried it on a group of images that needed a little tweaking and the 50% adjustments setting was perfect.
User avatar

2021-03-19 16:38:27

Andrius, I believe I was still getting an error message, I'll see if I can reproduce it.
User avatar

2021-04-05 05:19:36

Hi Andrius

I've been using Pixelmator Pro more and more frequently over the past year. The forums and your comments have been tremendously helpful.

Now, I'm trying some AppleScript and I'm new to that too but I have the basic framework working.

Overall goal: I am trying to create permutations of text and color combinations in a file based on input from a Numbers file

e.g., PUMPKIN (text) and Color (some RGB orange)
PUMPKIN (text) and Color (some RGB black)
HAT (text) and the same color variations etc.

My repeat loops seem fine

I am stuck on two points.

1 - changing color of text that was converted to shape

This works if I hardcode to something like {10000, 12543, 23808} instead of using TheFillColor variable
tell styles of current layer
	set fill color to TheFillColor
	set stroke color to TheFillColor
	set stroke width to (15)
end tell -- End Tell Styles
I am trying to populate TheFillColor from a Numbers file but cannot get the right format so that Pixelmator receives {10000, 12543, 23808}

I tried text in a single cell but then it seems Pixelmator gets
"{10000, 12543, 23808}"

text in multiple cells results in
{"10000", "12543", "23808"}

how do I enter values in a spreadsheet either in a single cell or multiple cells and communicate them to the script effectively?

2 - Rotating the text or text converted to shape

I tried rotate 5

the dictionary implies that rotate can take an argument, but it does not work for me (script fails/won't compile)

rotate 180 v : Rotate the entire image by 180 degrees.
rotate 180 document

rotate right v : Rotate the entire image by 90 degrees clockwise. syn rotate -90, rotate 270
rotate right document

rotate left v : Rotate the entire image by 90 degrees counterclockwise. syn rotate 90
rotate left document

thanks in advance!
User avatar

2021-04-06 09:24:56

Hi there, Tillie, really glad to hear you've found the forum useful! The first issue is that you're getting a string (some text) back rather than a number, as indicated by the quotation marks around it. You can coerce text to a number using the "as" operator like this:
set theNumber to "42" --> This looks like a number, but it's actually some text.
set theNumber to theNumber as number --> now theNumber variable is 42 instead of "42"
However, I think you shouldn't have to do this as you should be getting number values from Numbers cells. Could you share the part of your script that gets the values from Numbers?

The second issue is that the rotate command rotates the entire document, not individual layers. To do that, you'd need to set the layer's "rotation" property, like this:
tell application "Pixelmator Pro"
	tell the front document
		set the rotation of layer 1 to 90
	end tell
end tell
P.S. When sharing AppleScript on the forum, you can click the "Code" button at the top of the Post Reply form and that will add some AppleScript tags that will nicely format your scripts to make them easier to read. I've formatted yours for you by editing your post, I hope you don't mind.
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! 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 support@pixelmator.com? As it does sound like some sort of bug...