Local and cloud-based workflows for extracting and updating text layers in PSD files via ExtendScript and Adobe PS API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
166 lines
No EOL
5 KiB
Python
Executable file
166 lines
No EOL
5 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""
|
|
Extract Internal Layer IDs
|
|
|
|
This script runs the ExtendScript to extract internal layer IDs from a PSD file
|
|
and saves the result as a JSON file. This is critical for correctly identifying
|
|
text layers when using the Adobe Photoshop API.
|
|
|
|
Usage:
|
|
python extract_ids.py /path/to/file.psd
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
import json
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
def run_extract_script(psd_path):
|
|
"""
|
|
Run the ExtendScript to extract internal layer IDs
|
|
|
|
Args:
|
|
psd_path: Path to the PSD file
|
|
|
|
Returns:
|
|
Path to the generated JSON file
|
|
"""
|
|
# Get the absolute path to the PSD file
|
|
psd_path = os.path.abspath(psd_path)
|
|
|
|
# Check if the file exists
|
|
if not os.path.exists(psd_path):
|
|
print(f"Error: PSD file not found: {psd_path}")
|
|
return None
|
|
|
|
# Get the path to the JSX script
|
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
jsx_path = os.path.join(script_dir, "test", "extract_internal_ids.jsx")
|
|
|
|
# Check if the script exists
|
|
if not os.path.exists(jsx_path):
|
|
print(f"Error: JSX script not found: {jsx_path}")
|
|
return None
|
|
|
|
# Create the AppleScript to run the JSX script in Photoshop
|
|
applescript = f"""
|
|
tell application "Adobe Photoshop"
|
|
activate
|
|
open POSIX file "{psd_path}"
|
|
do javascript file "{jsx_path}"
|
|
end tell
|
|
"""
|
|
|
|
# Create a temporary AppleScript file
|
|
temp_as_path = os.path.join(script_dir, "temp_extract_ids.scpt")
|
|
|
|
try:
|
|
# Write the AppleScript to a temporary file
|
|
with open(temp_as_path, "w") as f:
|
|
f.write(applescript)
|
|
|
|
# Run the AppleScript
|
|
print(f"Opening {os.path.basename(psd_path)} in Photoshop...")
|
|
print(f"Running ExtendScript to extract internal layer IDs...")
|
|
|
|
result = subprocess.run(
|
|
["osascript", temp_as_path],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
print(f"Error running AppleScript: {result.stderr}")
|
|
return None
|
|
|
|
# Check for the output JSON file
|
|
psd_dir = os.path.dirname(psd_path)
|
|
psd_name = os.path.basename(psd_path).replace('.psd', '')
|
|
json_path = os.path.join(psd_dir, f"{psd_name}_internal_ids.json")
|
|
|
|
if os.path.exists(json_path):
|
|
print(f"Successfully extracted internal layer IDs to: {json_path}")
|
|
return json_path
|
|
else:
|
|
print(f"Warning: JSON output file not found at expected location: {json_path}")
|
|
return None
|
|
|
|
except Exception as e:
|
|
print(f"Error: {str(e)}")
|
|
return None
|
|
finally:
|
|
# Clean up the temporary AppleScript file
|
|
if os.path.exists(temp_as_path):
|
|
os.remove(temp_as_path)
|
|
|
|
def analyze_layer_ids(json_path):
|
|
"""
|
|
Analyze the extracted layer IDs
|
|
|
|
Args:
|
|
json_path: Path to the JSON file with layer data
|
|
|
|
Returns:
|
|
None
|
|
"""
|
|
if not json_path or not os.path.exists(json_path):
|
|
print("No JSON file to analyze")
|
|
return
|
|
|
|
try:
|
|
# Load the JSON data
|
|
with open(json_path, 'r') as f:
|
|
data = json.load(f)
|
|
|
|
# Extract the text layers
|
|
text_layers = data.get('textLayers', [])
|
|
|
|
if not text_layers:
|
|
print("No text layers found in the document")
|
|
return
|
|
|
|
print(f"\nFound {len(text_layers)} text layers in the document:")
|
|
print("=" * 70)
|
|
|
|
# Print layer information
|
|
print(f"{'Layer Name':<30} {'Direct ID':<10} {'Internal ID':<12} {'Text Content':<40}")
|
|
print("-" * 70)
|
|
|
|
for layer in text_layers:
|
|
name = layer.get('name', 'Unknown')
|
|
direct_id = layer.get('id', 'N/A')
|
|
internal_id = layer.get('internalID', 'N/A')
|
|
text = layer.get('text', 'No text')
|
|
|
|
# Truncate long text for display
|
|
if len(text) > 30:
|
|
text = text[:27] + "..."
|
|
|
|
# Replace linebreaks for display
|
|
text = text.replace('\r', '\\r')
|
|
|
|
print(f"{name:<30} {direct_id:<10} {internal_id:<12} {text:<40}")
|
|
|
|
print("\nIMPORTANT: Use the Internal IDs when calling the Adobe Photoshop API")
|
|
print(" These are the IDs that the API uses to identify text layers")
|
|
|
|
except Exception as e:
|
|
print(f"Error analyzing layer IDs: {str(e)}")
|
|
|
|
def main():
|
|
# Parse command-line arguments
|
|
parser = argparse.ArgumentParser(description="Extract internal layer IDs from a PSD file")
|
|
parser.add_argument("psd_file", help="Path to the PSD file")
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Run the extraction script
|
|
json_path = run_extract_script(args.psd_file)
|
|
|
|
# Analyze the results
|
|
analyze_layer_ids(json_path)
|
|
|
|
if __name__ == "__main__":
|
|
main() |