Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modifying Defined Image Variables, Saving change to ImageResources #375

Open
Investigamer opened this issue Oct 23, 2023 · 1 comment
Open

Comments

@Investigamer
Copy link

Hi there! I'm trying to modify an Image Resource, specifically the IMAGE_READY_VARIABLES which are variables in Photoshop used for Data Sets to govern a layer's visibility for example. Here you can see an example of the operation I'm performing:

# Boilerplate
from psd_tools import PSDImage
from psd_tools.constants import Resource
from psd_tools.psd.image_resources import ImageResource
import xml.etree.ElementTree as ET

"""
* Construct Variables XML
"""

# Create the root element
root = ET.Element('variableSets', xmlns="http://ns.adobe.com/Variables/1.0/")

# Create variableSet -> variables
variableSet = ET.SubElement(root, 'variableSet')
variableSet.set('locked', 'none')
variableSet.set('varSetName', 'binding1')
variables = ET.SubElement(variableSet, 'variables')

# Add variables, could do this programmatically for each layer
variable = ET.SubElement(variables, 'variable')
variable.set('varName', 'BorderCrop.Visible')
variable.set('trait', 'visibility')
variable.set('docRef', "id('19910')")

# Convert the XML to a string
xml_str = ET.tostring(root, encoding='utf8', method='xml', short_empty_elements=False).decode()

# Modify string to identically match previous data
xml_str = xml_str.replace('<?xml version=\'1.0\' encoding=\'utf8\'?>\n', '', 1).replace('><', '>\n<') + '\n'

"""
* Replace PSD XML
"""

# Open PSD and create new Image Resource with XML data
psd = PSDImage.open('my_file.psd'))
new_resource = ImageResource(b'8BIM', key=Resource.IMAGE_READY_VARIABLES, data=xml_str.encode())
    
# Replace with new resource and save
psd.image_resources[Resource.IMAGE_READY_VARIABLES] = new_resource
psd.save('my_file2.psd')

Just for a quick test, I decided to modify the replace the IMAGE_READY_VARIABLES with just one of the variables that already exists in the document, effectively trimming the other 2 variables. Here is the output when I read them originally:

b'<variableSets xmlns="http://ns.adobe.com/Variables/1.0/">\n<variableSet locked="none" varSetName="binding1">\n<variables>\n<variable varName="BorderCrop.Visible" trait="visibility" docRef="id(\'19910\')">\n</variable>\n<variable varName="PixelVariable1" trait="fileref" placementMethod="fit" align="center" valign="middle" clip="false" docRef="id(\'13420\')">\n</variable>\n<variable varName="VisibilityVariable1" trait="visibility" docRef="id(\'13420\')">\n</variable>\n</variables>\n</variableSet>\n</variableSets>\n'

Here is the output of what I changed it to:

b'<variableSets xmlns="http://ns.adobe.com/Variables/1.0/">\n<variableSet locked="none" varSetName="binding1">\n<variables>\n<variable varName="BorderCrop.Visible" trait="visibility" docRef="id(\'19910\')">\n</variable>\n</variables>\n</variableSet>\n</variableSets>\n'

Looks identical right? Welp, it may look totally correct BUT now when I open the PSD, Photoshop acts as though no variables are defined at all. I've now used this same process to define variables dynamically for each layer, among many other tests, I cannot get these variables written to this section to be recognized. Does anyone have any ideas? There is no way as far as I've found to modify defined variables in Photoshop using action descriptors or the Photoshop API so modifying them defined in the PSD file is my last hope. Any ideas to get this to work would be hugely appreciated!

@Investigamer
Copy link
Author

Investigamer commented Oct 23, 2023

I solved the issue! I was misled by the documentation on the ImageResource class, it says:

"""
py:attribute:: signature

        Binary signature, always ``b'8BIM'``.
"""

However the signature for Resource type IMAGE_READY_VARIABLES is actually b'MeSa', so when I change this line as follows:

new_resource = ImageResource(b'MeSa', key=Resource.IMAGE_READY_VARIABLES, data=xml_str.encode())

Now the data is represented correctly in Photoshop! 💪 Perhaps that comment should be edited since sometimes 8BIM is not the correct signature?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant