Some small differences are that I had to add a couple of flags to the comtypes object creation (which may have just been a quirk of my machine, see the stackoverflow link for details) and I've added some details about manipulating smart layers at the bottom of the snippet.
Happy coding!
##############################################################################
#
# Eight years later, here is my 2020 version of how to use Comtypes to drive photoshop
#
# Here is a quick code sample showing how to manage different layers and groups
# in a photoshop document using Python.
#
# Pete Hanshaw, 2020
# http://peterhanshawart.blogspot.com.au/
#
##############################################################################
#
# How to make a layerSet (aka, 'group') artLayer (aka 'layer'), how to make them
# active and how to move them.
#
# These examples use the comtypes module. Grab it here:
# http://sourceforge.net/projects/comtypes/
#
##############################################################################
#Create the application reference
import comtypes.client as ct
# https://stackoverflow.com/questions/42794530/error-pointeriunknown-when-trying-to-access-com-object-properties/42823644
psApp = ct.CreateObject('Photoshop.Application', dynamic=True)
psApp.Visible = True
#Create a new document to play with
doc = psApp.Documents.Add(256, 256, 72, 'test_bed', 2, 1, 1)
#When scripting 'groups' are called 'layerSets'.
new_layerSet = doc.LayerSets.Add()
#Once you create a layerSet object reference, you can access it's
#'name' attribute. The same goes for other objects you can normally
#name within Photoshop.
new_layerSet.name = "I'm a layerSet"
#regular, paintable layers are called 'ArtLayers'
new_art_layer = doc.ArtLayers.Add()
new_art_layer.name = "I'm an ArtLayer"
#To add a nested art layer into a LayerSet, use our layerSet object as a reference
nested_art_layer = new_layerSet.ArtLayers.Add()
nested_art_layer.name = "I'm a nested ArtLayer"
#The same goes for adding a nested LayerSet!
nested_layerSet = new_layerSet.LayerSets.Add()
nested_layerSet.name = "I'm a nested LayerSet"
#and so on!
deep_art = nested_layerSet.ArtLayers.Add()
deep_art.name = "Deep man, deep."
#Every time a new object is made, it will become the active layer.
#To make other layers active, you can refer to them either by their name, or
#their index location.
#For example:
#Making an art layer active using the layer's name:
doc.activeLayer = (doc.artLayers["I'm an ArtLayer"])
#Making an art layer active using the layer's index location:
doc.activeLayer = (doc.artLayers[-1]) #This will select the background!
#Selecting a nested art layer is a little more difficult, as you have to
#'drill down' through the hierachy in order to select it.
doc.activeLayer = (doc.layerSets["I'm a layerSet"].
layerSets["I'm a nested LayerSet"].
artLayers["Deep man, deep."])
#Moving a layer in the hierachy is done using the move command.
#The arguments specify which hierachy to move in, and where to put it.
#For example, this will move the first layerSet we made just above the background
#layer.
#Make a new layer set
mobile_layerSet = doc.LayerSets.Add()
mobile_layerSet.name = "move me"
#Move the 'mobile' layerSet to just after the 'background' layer
mobile_layerSet.Move(doc, 2)
# Smart Layer Manipulation Examples adapted from:
# https://www.photopea.com/tuts/edit-smart-objects-with-a-script/
# Create a smart object layer.
# CREATING A SMART LAYER
# select a layer that you want to work with
smart_layer = doc.ArtLayers.Add()
smart_layer.name = "Smarty pants Layer."
doc.activeLayer = smart_layer
# Convert the active layer into a smart object
psApp.executeAction(psApp.stringIDToTypeID("newPlacedLayer"));
# EDITING A SMART LAYER
# Now we can edit the smart object
psApp.executeAction(psApp.stringIDToTypeID("placedLayerEditContents"))
# now, the Smart Object is an active document, we can work with it. Rename the layer...
smartDoc = psApp.activeDocument
super_smart_layer = smartDoc.ArtLayers[0]
super_smart_layer.name = "Amazingly smart layer."
# save the smart object and close it
psApp.activeDocument.save()
psApp.activeDocument.close()
# We are now back in the root object
# QUERYING A SMART LAYER
# If we want to check if a layer is smart, we can query it...
doc = psApp.activeDocument
for layer in doc.ArtLayers:
# 17 is a psSmartObjectLayer - see the Adobe Scripting API 'PsLayerKind' to see what each value means.
if layer.Kind == 17:
print "We found a smart layer named {}".format(layer.name)
Yes! Thank you.
ReplyDeleteQuick quesiton - What if we're not creating the layers, but accessing existing smart layers? Is it as simple as setting the:
psApp.Application.ActiveDocument.activeLayer = layer/.name?
and then:
psApp.executeAction(self.psApp.stringIDToTypeID("placedLayerEditContents"))
Cheers mate!
Figured it out :D
DeleteThanks!
I am doing everything in a class. the self.psdDict has all the different layers of the master psd stored.
for layer in self.psdDict['smartObjects']:
try:
self.psdDoc.activeLayer = layer
self.psApp.executeAction(self.psApp.stringIDToTypeID("placedLayerEditContents"))
print layer.name, '<-'
smartDoc = self.psApp.activeDocument
self.psApp.activeDocument.close()
doc = psApp.activeDocument
except:
print 'passed on something here.'
pass