I just wanted to thank everyone from the Pixelmator team for allowing us to automate some image generation. There's only a few resources out there but I was able to cobble together something that's working and gets the job done, and I wanted to share for others out there. This is just my work in progress, and I still have to figure out how to select subsections of text and change their colors among a few other tasks, but this is some of the hardest -get-off-the-ground- kind of work for others looking to do something similar to what I'm doing here.
I wish there was a better language than Applescript to automate these tasks with (If you're reading this Pixelmator team, is there some Swift integration planned for the future?) because Applescript is just majorly lacking for doing even basic tasks like JSON Serialization...but I digress! Sometimes we work with only the tools we have.
If you find this useful please check out my youtube channel over at https://youtube.com/echohack
So my main problem here is that I need to generate TONS of assets (hundreds and hundreds) for using in my videos, socials, etc. and I want to do this programmatically because I need to regenerate these assets every few months based on changing data. Doing this by hand takes about 50 hours of work! Every time! So it's a prime candidate for automation. (Obligatory XKCD) https://xkcd.com/1319/
So I have a big blob of JSON data that I want to programmatically iterate over, insert into Pixelmator, and generate a bunch of images from a template and then export all of them.
Again nothing here is optimized, but this does work! Some refactoring into methods-- uh-- Handlers is probably called for here. Whatever. It's Applescript, it's allowed to suck a bit OK?
One annoying thing here is that there doesn't seem to be a way to replace text *only* on the currently selected layer, and also there isn't an easy way to select the *next* layer in a list. So instead of wrestling Applescript's nonsense, I'm just generating them all from a single template and copy-pasting that template, and then using layer visibility's boolean as a kludge to tell the iterator that I'm done with that layer. It's not something I'd put in professional code per se but hey it works here. This does have the annoying effect of copying and pasting all over the place, which is kind of slow, especially as you get into the hundreds of grouped layers. Oh well. Don't use this to generate 100,000 images ok?
use framework "Foundation"
use scripting additions
--------------------------------------------------------------------------------
# Helper Libraries
property ca : a reference to current application
property NSData : a reference to ca's NSData
property NSDictionary : a reference to ca's NSDictionary
property NSJSONSerialization : a reference to ca's NSJSONSerialization
property NSString : a reference to ca's NSString
property NSUTF8StringEncoding : a reference to 4
on JSONtoRecord given item:fp
local fp
set JSONdata to NSData's dataWithContentsOfFile:fp
set [x, E] to (NSJSONSerialization's ¬
JSONObjectWithData:JSONdata ¬
options:0 ¬
|error|:(reference))
if E ≠ missing value then error E
tell x to if its isKindOfClass:NSDictionary then ¬
return it as record
x as list
end JSONtoRecord
--------------------------------------------------------------------------------
set home to the path to home folder
set f to the POSIX path of home & "blob.json"
set testRecord to JSONtoRecord given item:f
tell application "Pixelmator Pro"
# Generate the Images
tell the front document
set visible of every layer to true
repeat with jsonList in (testRecord as list)
repeat with listItem in (jsonList as list)
if visible of current layer then
set name of current layer to (|Class| of listItem) & " - " & (|listName| of listItem)
copy
set listCategory to (|Category| of listItem)
set listName to (|Name| of listItem)
set listEffect to (|Effect| of listItem)
replace text "listEffect" with listEffect
replace text "listName" with listName
replace text "listCategory" with listCategory
set visible of current layer to false
paste
end if
end repeat
end repeat
end tell
# Export the images
set exportLocation to choose folder with prompt "Choose where to export the images:"
tell the front document
set visible of every layer to false
set visible of the last layer to true
repeat with currentLayer in every layer
set visible of currentLayer to true
export for web to ((exportLocation as text) & name of currentLayer & ".png") as PNG with properties {compression factor:100}
set visible of currentLayer to false
end repeat
end tell
end tell