Pre Reqs:
- Ability to read and understand javascript
- Writing Adobe Scripts in Javascript
- Python Knowledge and practices
- PySide or TkInter Knowledge
- Basic Troubleshooting
Tools:
- Adobe Documentation Javascript Guide
- Adobe SDK
- Pycharm (or preferred python IDE)
Intro:
Hello out there. If you are reading this then you either want to save yourself time, save someone else time or you want to make a cross platform application without developing an adobe plugin.
Whatever your reason you will learn the various situations this skill may be useful and I will cover a lot of the headaches of digging through undocumented functions to deliver a final product.
Warning – You cannot use this technique to write Generator Scripts due to generator needing to access node.js
What you will learn:
- The major difference between Javascript and Python
- How to convert javascript scripts to python scripts
- Using the Action Manager
- Using COM in Python
- Finding functions not documented in adobe documentation
- How to troubleshoot to find the information you need
Getting Started:
If you haven’t done so please go through http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/photoshop/pdfs/photoshop-cc-scripting-guide.pdf
File() Folder() vs path module
In Javascript you access files and folders with a File() or Folder() Object. You can then do logic checks to see if a var type equals either object.
In python you have to check if the provided path is a directory or a file.
For Loops
The easiest way to re-implement the a for I = 0; I < x; i++ is by using for I in range (0,x)
How to Convert a Function from Javascript to Python
There are 4 major Find Replace Search’s which will take care of 90% of all work involved
- Find (;) Replace with () <-nothing
- Find (var) Replace with () <-nothing
- Find ({) Replace with (:) <-Colon
- Find (}) Replace with () <-nothing
- Find (new) Replace with () <-nothing
Other than that you want to:
- switch out function with def
- Ensure all logic is converted to a python acceptable format
- No Switch Statements unless you have a dictionary. Alternatives link(Resource Link)
- Readable Switch Construction – http://code.activestate.com/recipes/410692/
- Exception Based Switch Case – http://code.activestate.com/recipes/410695/
- Using Dictionaries for switch cases http://code.activestate.com/recipes/181064/
- For loops need to be re-worked
- You have options to now check:
- For Object in Parent:
- For IncrementValue in range(0,len(Object))
- Bools in Javascript are true/f In Python it is True/False
- Ensure proper indentation (Due to python)
Example:
Before: After:
How to connect python to Photoshop:
Using win32COM Library
For Photoshop the registry is Photoshop.Application.80
- Dispatch Connection to Adobe Registry Remember to use:80 to reference the latest version of photoshop
Using comtypes Library
If you do not have comtypes library use pip –install comtypes
For Photoshop the registry is Photoshop.Application.80
- Create a Connection to Application Registry. Remember to use :80 to reference the latest version of application
Finding functions not documented in adobe documentation
This caused me some trouble while trying to use dot notation for ArtLayers and LayerSets.
To find the python equivalent of all functionality available the easiest way is to use makepy.py to create an API form the Adobe Photoshop object Library.
How I used Makepy.py
- Create a new Python Script
- Import makepy and genCache modules from win32com.client
- Run the main() function for makepy
- Use gen cache to return Generated python file path
- Run Script and select the Photoshop Object Library
- Navigate to path and copy file to local directory
How to use this file
Open the generated file with your chosen IDE – you will see the Generated Constants that PS uses to hold all enums, then all classes with their parameters.
To access all these functions in your script you only have to call the Dispatch object you created and use dot notation to call the function or variable.
For Ex:
psApp = CreateObject(“Photoshop.Application.80”)
artLayers = psApp.activeDocument.artLayers
Using the Action Manager to optimize your script
This is the fun part of Adobe Photoshop in my opinion – though it is hard to get a grasp for the lack of documentation I am going to try to simplify this as much as possible.
Why use Action Manager for every command you can?
You want a performance friendly automation tool? Every access to the DOM is going to cost you atleast a second of processing time – it’s just the facts. ActionManager utilized a lower level access to photoshop objects and commands – BUT THERES NO DOCUMENTATION. You have to use script listener to find out what actions you have access to.
Please follow the Adobe Scripting guide for usage and installation of the script listener
Resources before you begin
You are going to need a way to understand what each string or type id means.
I Use http://www.pcpix.com/photoshop/enum.htm
This is a type to plain English translation of all enum’s the action manager can use
Classes you will need to have
How to read an action
Throughout working with action manager I have broken down build of and reading of an action into 3 parts. Description, Reference, Execution.
Warning: This is my personal way of viewing the action manager. It could be wrong but it works for my understanding
- Define a description of the Action
- Build a reference to the Action
- Execute the Action
Lets take a well known example which is SetActiveLayerByIndex().
- First you are Initializing a new Action Description and Reference
- The object you are referencing is a Layer(Lyr ) Object with an index of idx
- You are adding this reference as the default reference object to the Action Description (Which describes the action you want to execute). This default reference is noted with the “null” value
- You are adding a special parameter to MakeVisible(MKVs) and setting visibility to parameter
- You are Executing the Action “Select” with the current photoshop Dispatch Object, we don’t want any dialogs so we use no dialogs or the int(3)
Boom you’ve just set active layer by index.
Lets take a more obscure example and break it down. Lets offset the active layer by an x,y amount
- So here we are Getting the TypeID for Transform. Transform controls the position, scale and rotation of our asset.
- We are creating a description for the mainEventDetails to add our references and special commands
- We are getting the FreeTransform TypeID, QuadCenterState since we are working with a four sided flat object, then we get the Average(Exact Middle) of the CenterState
- We are setting this as the target for our action so we put in this information as an enumeration
- We now create a separate description which will tell our action how much to offset the FreeTransform.(Each different action taken requires another description. First we set our target then we set what happens to our target)
- We get the Type ID for Horizontal Offset by Pixels
- We build an enumeration with a UnitDouble(The offset amount passed through the parameters)
- We get the Type ID for Vertical Offset by Pixels
- We build an enumeration with a UnitDouble(The offset amount passed through the parameters)
- We cache the type ID for the Offset Command
- Afterwards we build the description for the Offset Event in the MainEventDetails. (Sinze it needs to be added as an enumeration we reference idOffset twice then the details)
- We execute the Transform Event with the mainEventDetails as the description for the transform event. We don’t want any dialogs so we use no dialogs.
If you wanted user input you would set to show dialogs then the user can control the positioning of the active layer.
Final Words
This is meant to serve as a guide for you to create python scripts that run in photoshop. With python you can connect to any other application and gather information.
I wrote a translations script which takes keys from an excel document, iterates over all text layers and upon finding a key replaces and formats the text with the new foreign language value from the excel document
Resource Links:
http://www.adobe.com/devnet/photoshop/scripting.html –Contains API’s for JavaScript and scripting tutorials
http://www.adobe.com/devnet/photoshop/sdk.html – Adobe Photoshop SDK for locating PSContants and other built-in classes
http://www.pcpix.com/photoshop/enum.htm – Action Manager ID’s List
http://www.tonton-pixel.com/blog/wp-content/uploads/DecisionTable.pdf – Decision Table for conflicting String ID’s
http://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python – Switch Case Replacement Discussion