Automating image processing on Photoshop using Python
1. Generating images
2. Smart objects?
3. Python and COM
4. Basic Recipe
5. A step further
6. Watch out!
7. Hope this was useful
Here’s the Adobe documentation my work was based on.
Here’s a link to another project that could also be of interest. I have not used their code, but it looks very promising.
The sample code and repo source code have been tested on Python 2.7, but should work fine on Python 3.
Source code
2. Smart objects?
3. Python and COM
4. Basic Recipe
5. A step further
6. Watch out!
7. Hope this was useful
Generating images
Some time ago we needed a solution to be able to quickly generate some product images using Photoshop. The graphic designer wanted to combine 2 images into a final product image to be used to display their products online.- An environment image (PSD file).
- An object image (jpg).
- Combine the above images into a product image (jpg).
PIL
, Skimage
, OpenCV
would work fine!
Well, in this case, there were some very fine transformations and image processing being done in Photoshop and the graphic designer needed all these features required in order to generate high-quality images using filters, shears and other exotic (for me at least) visual effects.
Smart objects?
Prior to my involvement, the graphic designer had been looking for a way to simplify and automate this image generation process. An important feature that would be key to this work is the concept of Smart Objects Smart objects in Photoshop allow you to ‘link’ 2 or more PSD files.Any changes made to the linked PSD are automatically made to any PSD linking to it!Basically, you create a PSD file and have one of the layers act as a Smart Object. Then you link that Smart Object layer to another PSD. Afterward when you open the background image and the product image in Photoshop, any changes you make to the product image, also are made in the background image. Another cool thing about Smart Objects is that all the transformations within the Smart Object layer are preserved, regardless of the changes you make to the source PSD.
- Each background image (PSD) must contain a layer with a Smart Object.
- The Smart Object layer has to be linked to a default image (PSD).
- Works best if both PSD files reside in the same directory.
- Open the background image in Photoshop (mountains).
- Open the default product image in Photoshop (ball).
- Open the desired product image in Photoshop (star).
- Copy the desired product image into the default product image. This updates the Smart Object.
- Save the background image as JPEG. This is our final image we want to generate with mountains and the star.
- Repeat this for every background/product combination image we want to generate.
Python and COM
As mentioned at the beginning, we will be using the Photoshop COM programming interface. The Photoshop reference PDF will be our guide in writing our automation scripts. Of course, we could be doing this directly in the VB script, but it is much more fun (and productive!) to use Python. Here’s a basic sample that opens an image in Photoshop.import win32com.client
# This actually fires up Photoshop if not already running.
ps = win32com.client.Dispatch("Photoshop.Application")
# Open an image file (PSD in our case)
doc = ps.Open(r"X:\Path\To\My.psd")
# ... do something ...
doc.Close()
ps.Quit() # Stops the Photoshop application
Basic Recipe
Here is some basic sample code that illustrates the automated steps to generate our final product image, which is a star on a background of mountains. Notice also that we duplicate the PSD documents once we open them. We do this in order not to accidentally change and save the original PSD files. Important: working with Photoshop’s object containers is different from the native Python lists and tuples. The indices are 1-based, so the first element of the container hasindex=1
(as opposed to index=0 as per usual).
basic_recipe.py
import os
import win32com.client
SILENT_CLOSE = 2
curdir = os.path.abspath(os.path.dirname(__file__))
background_path = os.path.join(curdir, "background.psd")
ball_base_path = os.path.join(curdir, "C base.psd")
star_path = os.path.join(curdir, "star.jpg")
gen_path = os.path.join(curdir, "final.jpg")
# This actually fires up Photoshop if not already running.
ps = win32com.client.Dispatch("Photoshop.Application")
ps.DisplayDialogs = 3 # psDisplayNoDialogs
ps.Preferences.RulerUnits = 1 # psPixels
"""1. Open the background image in Photoshop (mountains)."""
bg = ps.Open(background_path)
background = bg.Duplicate() # Work with a clone
bg.Close(SILENT_CLOSE)
"""2. Open the default product image in Photoshop (ball)."""
ball = ps.Open(ball_base_path)
ball_layer = ball.ArtLayers.Item(1)
"""3. Open the desired product image in Photoshop (star)."""
target = ps.Open(star_path)
star = target.Duplicate()
target.Close(SILENT_CLOSE)
"""4. Copy the desired product image into the default product image.
This also updates our background image."""
# Place copy of desired product image on clipboard
star_layer = star.ArtLayers.Item(1)
star_layer.Copy()
star.Close(SILENT_CLOSE)
# Set as active image in Photoshop
ps.ActiveDocument = ball
# Paste 'star' image from clipboard
pasted = ball.Paste()
# We apply new image to smart object layer.
ball.Save()
"""5. This is our final image we want to generate with mountains and the star."""
jpgSaveOptions = win32com.client.Dispatch( "Photoshop.JPEGSaveOptions" )
ps.ActiveDocument = background
background.SaveAs(gen_path, jpgSaveOptions, True, 2)
background.Close(SILENT_CLOSE)
ball.Close(SILENT_CLOSE)
ps.Quit() # Stops the Photoshop application
A step further
In order to make this a little less painful to use, we created a psd_utils.py source file. This file contains the Photoshop class to alleviate some boilerplate code.ps_sample.py
import os
from psdbase_utils import Photoshop
curdir = os.path.abspath(os.path.dirname(__file__))
background_path = os.path.join(curdir,"background.psd")
star_path = os.path.join(curdir,"star.jpg")
ps = Photoshop()
all_open_psd =\
ps.compose(background_path,
star_path,
"C base",
curdir,
"final.jpg")
for open_psd in all_open_psd:
ps.close(open_psd)
ps.shutdown()
Watch out!
As mentioned earlier, even though there are quite a few advantages to automating with Photoshop, there are also quite a few points to consider. Photoshop scripts require running an actual instance of Photoshop and it’s main window will be visible on the desktop. The Photoshop window should not be minimized while running a script. This might actually block Photoshop and prevent your automated task from running properly. If you make use of Copy/Paste commands in your script, this will hijack your clipboard, and prevent any other user/application from using it properly. Photoshop tends to hang/freeze/crash periodically. The crashes are frequent on big batches of images and don’t seem to be related to RAM/CPU usage. Just restart your script and it will eventually run to completion just fine. Regardless of crashes, you can still make huge productivity gains from automating some tasks. For all these reasons, we highly recommend that any automated tasks you create should run on a dedicated Windows PC. You don’t need a high-end PC for most tasks and this will definitely make everyone more productive.Hope this was useful
Of course, most of the code and samples discussed here are related to the specific use case described. Almost all Photoshop commands can be scripted this way. The sample code should help you get started, and more details can be found in the Photoshop scripting reference. If you need any help with your project, we will gladly share our expertise if required!About Author
David Vaillancourt
Been working as a developer for 20+ years, started on the Commodore Vic-20 (I'm old!). I've worked in the video game industry and also recently completed an important computer vision project in the pharmaceutical field. Anything requring some creative thinking and problem solving really interests me, my curiousity is boundless.
Please share your Feedback:
Did you enjoy reading or think it can be improved? Don’t forget to leave your thoughts in the comments section below! If you liked this article, please share it with your friends, and read a few more!