Automating PhotoShop Tasks Using PhotoShop APIs.
by WeblashAdmin on Sep.27, 2009, under C#, development
Melchor Berona of Photo-Essence recently hired me to design his website. One of his feature requests was to enable a fast, easy way to get photos to his galleries online. This sounds simple enough, I thought, and off I went.
As for any business, Melchor didn’t want to spend valuable hours replacing images in his online photo galleries. He wanted to get the high resolution photos to a usable format and size; then FTP to his site. The process turned out to be this:
- Get images to 96ppi
- Convert images to RGB
- Resize landscape or portrait to 600px height
- Save file with the correct filename to be used in the destination galleries – old files would be swapped with new files, so the naming on the new images needed to be the same as the images being replaced
- Create thumbnail images that are 150x150px
- save file with the appropriate naming
- FTP the new files (not covered here)
So I thought: I’ll just create a droplet – no problem, right? Well, it’s not ideal when you’re resizing both landscape and portraits using the scaling in PhotoShop. This really can’t be automated unless you make two separate droplets, one for landscape and one for portrait.
Then I discovered a folder in the PhotoShop directories (in the Programs directory) that gives a pretty good introduction to automating tasks (and more) using scripting in JavaScript, VBScript, or ActionScript.
OK – now we’re getting somewhere, I thought. However, I wanted to take this a step further. I wanted to make a C# console application using the PhotoShop APIs. I didn’t find much documentation, but I did find a very good tutorial by John Deurbrouck here: http://www.pcpix.com/Photoshop/.
After I read that I was on my way. For this blog entry, I’d like to walk through my process of developing the application I delivered to my client.
Step 1 – Do Some Research
Get information on PhotoShop Scripting here: http://www.adobe.com/devnet/photoshop/scripting/
There are some PDFs here that go into detail about scripting for VB, JavaScript, and AppleScript. There’s also information about the ScriptListener.
Step 2 – turn on the ScriptListener
The PhotoShop ScriptListener logs every event you do in PhotoShop, from opening a document, modifications, saving, and closing it. So it should only be turned on when you are performing the steps you’ll use for your automation application. From Adobe…
Installing ScriptListener
The ScriptListener plug-in is located in the ..\Adobe Photoshop CS4\Scripting\Utilities folder.
To install the ScriptListener:
- Select the file ScriptListener.8li and then choose Edit > Copy.
- Paste the file copy to the following location: ..\Adobe Photoshop CS4\Plug-Ins\Automate
- Open Photoshop.
- NOTE: If Photoshop is already open, close it and then start it again. This will allow Photoshop to load
the plug-in.
- NOTE: If Photoshop is already open, close it and then start it again. This will allow Photoshop to load
To uninstall the ScriptListener:
- Close Photoshop.
- Verify that a copy of the file ScriptListener.8li still exists in the ..\Adobe Photoshop CS4\
Scripting\Utilities folder. - Delete the file ScriptListener.8li from the following location: ..\Adobe Photoshop CS\Plug-Ins\Automate
- Delete the log files ScriptingListenerJS.log and ScriptingListenerVB.log from your desktop.
- NOTE: In Windows, even though you remove the ScriptListener from the Automate folder, it may continue
to record actions. To prevent the ScriptingListenerJS.log file from becoming too large, delete it each
time you finish playing a Photoshop action.
- NOTE: In Windows, even though you remove the ScriptListener from the Automate folder, it may continue
So when you’re ready to simulate an automation, go to your Actions, create a new action, and start going through the steps. When you’re finished, you’ll see two files on your desktop:
ScriptingListenerJS.log, containing JavaScript code
ScriptingListenerVB.log, containing VBScript code
These files contain – you guessed it, the steps you just performed when you created the action.
Now you can see the code that defined the steps in the action. From here you can convert these steps to C# with some help from the documentation by John Deurbrouck here: http://www.pcpix.com/Photoshop/.
Step 3 – Write your functions
I created a separate class in my application that contains all the PhotoShop action steps (opening the file, resizing, saving, changing canvas size, etc.). Below is an example:
public static void Resize(int iHeight, string category) { //get the original document dimensions double dWidth = getdim("X"); double dHeight = getdim("Y"); //convert datatype of iHeight double dNewHeight = Convert.ToDouble(iHeight); switch (category) { case "full": break; case "mid": //is the document landscape or portrait? if (dWidth < dHeight) { //is portrait dNewHeight = 300; } else { dNewHeight = 200; } break; case "thumb": //is the document landscape or portrait? if (dWidth < dHeight) { //is portrait dNewHeight = (dHeight * dNewHeight) / dWidth; } break; } //run the action //describe the action int idImgS = app.CharIDToTypeID("ImgS"); ps.ActionDescriptor desc3 = new ps.ActionDescriptor(); //image height int idHght = app.CharIDToTypeID("Hght"); //image resolution int idPxl = app.CharIDToTypeID("#Pxl"); //not sure what the below does desc3.PutUnitDouble(idHght, idPxl, dNewHeight); //scale the styles too? int idscaleStyles = app.StringIDToTypeID("scaleStyles"); desc3.PutBoolean(idscaleStyles, true); //the canvas? int idCnsP = app.CharIDToTypeID("CnsP"); desc3.PutBoolean(idCnsP, true); //not sure what these do int idIntr = app.CharIDToTypeID("Intr"); int idIntp = app.CharIDToTypeID("Intp"); int idBcbc = app.CharIDToTypeID("Bcbc"); //add the properties to prep execution desc3.PutEnumerated(idIntr, idIntp, idBcbc); //run execution of action app.ExecuteAction(idImgS, desc3, ps.PsDialogModes.psDisplayNoDialogs); }
So I have to admit it’s been quite a while since I wrote the code, and I am sketchy about defining the actions. http://www.pcpix.com/Photoshop/ has all the details about just what the code is that defines the action, and lists all of the enum names and values. I have asked John Deurbrouck and pcpix.com if I can distribute the article as a Word doc from my blog. I’ll keep you updated.
If you take on a project like this, you’ll find you’ll need to do some conversions from the code in the ScriptListener file to the C# code for the actions to get prepped properly.
Anyhow, this is a start. Please send me feedback! I’m not an experienced blogger so comments would be helpful.













