Skip to content

Commit

Permalink
Added better macOS/appscript documentation.
Browse files Browse the repository at this point in the history
Added appscript based variants of sample code.
  • Loading branch information
oh-ok committed Jul 9, 2023
1 parent 6b97da9 commit 2a4456a
Show file tree
Hide file tree
Showing 22 changed files with 628 additions and 7 deletions.
20 changes: 20 additions & 0 deletions mac_scripting/ActiveLayer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Set the active layer to the last art layer of the active document, or the
# first if the last is already active.

from appscript import app, k
ps = app(id="com.adobe.Photoshop", terms="sdef")

# We could also use "ps.count(None, k.documents)" here, if
# we expect many documents to be open and speed was of concern.
if len(ps.documents()) < 1:
docRef = ps.make(new=k.document)
else:
docRef = ps.current_document

if len(docRef.layers()) < 2:
docRef.make(new=k.art_layer)

if docRef.current_layer() != docRef.layers[-1]():
docRef.current_layer.set(docRef.layers[-1])
else:
docRef.current_layer.set(docRef.layers[1])
32 changes: 32 additions & 0 deletions mac_scripting/ApplyCrystallizeFilterAction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# This script demonstrates how you can use the action manager
# to execute the Crystallize filter.

from os.path import abspath
from appscript import app, mactypes

# Start up Photoshop application
ps = app(id="com.adobe.Photoshop", terms="sdef")

# This must be an absolute path.
fileName = abspath("../PS_Samples_Files/Layer Comps.psd")
ps.open(fileName)
docRef = ps.current_document()

nLayerSets = docRef.layer_sets
nArtLayers = docRef.layer_sets[-1].art_layers

# get the last layer in LayerSets
docRef.current_layer.set(docRef.layer_sets[-1].art_layers[-1])

# custom actions like this must be done as Javascript, unfortunately
def applyCrystallize(cellSize):
script = """
cellSizeID = charIDToTypeID("ClSz");
eventCrystallizeID = charIDToTypeID("Crst");
filterDescriptor = new ActionDescriptor();
filterDescriptor.putInteger(cellSizeID, arguments[0]);
executeAction(eventCrystallizeID, filterDescriptor);
"""
ps.do_javascript(script, with_arguments=[cellSize])

applyCrystallize(25)
61 changes: 61 additions & 0 deletions mac_scripting/ApplyFilters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# This sample script shows how to apply 3 different filters to
# selections in the open document.

from os.path import abspath
from appscript import app, k, mactypes

# Start up Photoshop application
ps = app(id="com.adobe.Photoshop", terms="sdef")

# We don't want any Photoshop dialogs displayed during automated execution
ps.display_dialogs.set(k.never)

start_rulers = ps.settings.ruler_units.get()
ps.settings.ruler_units.set(k.pixel_units)

# This needs to be an absolute path
fileName = abspath("../PS_Samples_Files/Layer Comps.psd")
ps.open(fileName)
docRef = ps.current_document()

docRef.current_layer.set(docRef.layer_sets[-1].art_layers[-1])
active_layer = docRef.current_layer()

sel_area = ((0, 212), (300, 212), (300, 300), (0, 300))
ps.select(
docRef, region=sel_area, combination_type=k.replaced, feather_amount=20, antialiasing=True
)

active_layer.filter(
using=k.add_noise,
with_options={k.amount: 15, k.distribution: k.Gaussian, k.monochromatic: False}
)

ps.background_color.set({k.class_: k.HSB_color, k.hue: 0, k.saturation: 0, k.brightness: 100})


sel_area2 = ((120, 20), (210, 20), (210, 110), (120, 110))
ps.select(
docRef, region=sel_area2, combination_type=k.replaced, feather_amount=25, antialiasing=False
)

active_layer.filter(
using=k.diffuse_glow,
with_options={k.graininess: 9, k.glow_amount: 12, k.clear_amount: 15}
)

active_layer.filter(
using=k.glass_filter,
with_options={
k.distortion: 7,
k.smoothness: 3,
k.scaling: 7,
k.invert_texture: False,
k.texture_kind: k.tiny_lens
}
)

docRef.deselect()

# Set ruler units back the way we found it
ps.settings.ruler_units.set(start_rulers)
12 changes: 12 additions & 0 deletions mac_scripting/CompareColors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This script compares the app.foregroundColor
# to the app.backgroundColor.

from appscript import app

# Start up Photoshop application
ps = app(id="com.adobe.Photoshop", terms="sdef")

if ps.foreground_color() == ps.background_color():
print("They're Equal")
else:
print("NOT Equal")
11 changes: 11 additions & 0 deletions mac_scripting/ConvertColor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Convert the foreground color to RGB.

from appscript import app, k

ps = app(id="com.adobe.Photoshop", terms="sdef")

fgColor = ps.foreground_color

# Unlike JavaScript and COM, we have to use a function to convert colors
fgRGBColor = fgColor.convert_color(to=k.RGB)
print(f"Red: {fgRGBColor[k.red]} Green: {fgRGBColor[k.green]} Blue: {fgRGBColor[k.blue]}")
57 changes: 57 additions & 0 deletions mac_scripting/CopyAndPaste.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# This example makes a creates a selection in the activeDocument, copies the selection,
# to the clipboard, creates a new document of the same dimensions
# and pastes the contents of the clipboard into it.
# It ensures that rulerUnits are set before creating the new document.
# It checks the kind of the layer before making the selection to be
# sure not to copy a text layer.

from appscript import app, k

ps = app(id="com.adobe.Photoshop", terms="sdef")

strtRulerUnits = ps.settings.ruler_units()
ps.settings.ruler_units.set(k.inch_units)

srcDoc = ps.make(
new=k.document,
with_properties={k.width: 7, k.height: 5, k.resolution: 72, k.mode: k.RGB, k.initial_fill: k.white}
)

# Make sure the active layer is not a text layer, which cannot be copied to the clipboard
if srcDoc.current_layer.kind() != k.text_layer:
# Select the left half of the document. Selections are always expressed
# in pixels regardless of the current ruler unit type, so we're computing
# the selection corner points based on the inch unit width and height
# of the document
x2 = (srcDoc.width() * srcDoc.height()) / 2
y2 = srcDoc.height() * srcDoc.resolution()

sel_area = ((0, 0), (x2, 0), (x2, y2), (0, y2))
srcDoc.select(
region=sel_area,
combination_type=k.replaced,
feather_amount=0,
antialiasing=False
)

# AppleScript implementation of this function
# can only copy and paste from the current_document
# and only if it is the frontmost application
ps.activate()
ps.copy()

# The new doc is created
# need to change ruler units to pixels because x2 and y2 are pixel units.
ps.settings.ruler_units = k.pixel_units
pasteDoc = ps.make(
new=k.document,
with_properties={
k.width: x2, k.height: y2, k.resolution: srcDoc.resolution(), k.name: "Paste Target"
}
)
ps.paste()
else:
print("You cannot copy from a text layer")


ps.settings.ruler_units.set(strtRulerUnits)
25 changes: 25 additions & 0 deletions mac_scripting/CopyAndRotate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Crop and rotate the active document.

from os.path import abspath
from appscript import app, k, mactypes

# Start up Photoshop application
# Or get Reference to already running Photoshop application instance

ps = app(id="com.adobe.Photoshop", terms="sdef")

# This must be an absolute path
fileName = abspath("../PS_Samples_Files/Layer Comps.psd")
ps.open(fileName)
srcDoc = ps.current_document()

strtRulerUnits = ps.settings.ruler_units()
ps.settings.ruler_units.set(k.pixel_units)

# crop a 10 pixel border from the image
bounds = [10, 10, srcDoc.width() - 10, srcDoc.height() - 10]
srcDoc.rotate_canvas(angle=45)
srcDoc.crop(bounds=bounds)

# set ruler back to where it was
ps.settings.ruler_units.set(strtRulerUnits)
31 changes: 31 additions & 0 deletions mac_scripting/EmbossAction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# This script demonstrates how you can use the action manager
# to execute the Emboss filter.
# Inorder to find all the IDs, see https://helpx.adobe.com/photoshop/kb/downloadable-plugins-and-content.html#ScriptingListenerplugin
# This blog here exlains what a script listener is http:https://blogs.adobe.com/crawlspace/2006/05/installing_and_1.html

from os.path import abspath
from appscript import app, k, mactypes

# Start up Photoshop application
ps = app(id="com.adobe.Photoshop", terms="sdef")

fileName = abspath("../PS_Samples_Files/Layer Comps.psd")
ps.open(fileName)
docRef = ps.current_document()

docRef.current_layer.set(docRef.layer_sets[-1].art_layers[-1])

# Unfortunately, since there is no way to send raw Photoshop actions
# via AppleScript, we must use JavaScript for this
# Note: ScriptListener generated code looks awful, but you can tidy it up quite a lot ;)
def emboss(angle, height, amount):
ps.do_javascript("""
var desc = new ActionDescriptor()
var c = charIDToTypeID
desc.putInteger(c("Angl"), arguments[0])
desc.putInteger(c("Hght"), arguments[1])
desc.putInteger(c("Amnt"), arguments[2])
executeAction(c("Embs"), desc)
""", with_arguments=[angle, height, amount])

emboss(120, 10, 100)
29 changes: 29 additions & 0 deletions mac_scripting/FillSelection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Fill the current selection with an RGB color.

from appscript import app, k

# Start up Photoshop application
ps = app(id="com.adobe.Photoshop", terms="sdef")

strtRulerUnits = ps.settings.ruler_units()

if len(ps.documents()) < 1:
ps.settings.ruler_units.set(k.pixel_units)
docRef = ps.make(
new=k.document,
with_properties={
k.width: 320, k.height: 240, k.resolution: 72, k.mode: k.RGB, k.initial_fill: k.white
}
)
docRef.make(new=k.art_layer)
ps.settings.ruler_units.set(strtRulerUnits)

if ps.current_document.current_layer.background_layer() == False:
selRef = ps.current_document.selection
# Note the "_" here in both RGB_color_ and class_
fillcolor = {k.class_: k.RGB_color_, k.red: 255, k.green: 0, k.blue: 0}
selRef.fill(
with_contents=fillcolor, blend_mode=k.normal, opacity=25, preserving_transparency=False
)
else:
print("Can't perform operation on background layer")
12 changes: 12 additions & 0 deletions mac_scripting/HelloWorld.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Hello World!

from appscript import app, k

ps = app(id="com.adobe.Photoshop", terms="sdef")
doc = ps.make(new=k.document, with_properties={k.width: 320, k.height: 240})
layer_ref = doc.make(new=k.art_layer, with_properties={k.kind: k.text_layer})


text_item = layer_ref.text_object
text_item.contents.set("HELLO WORLD")
text_item.position.set([120, 120])
24 changes: 24 additions & 0 deletions mac_scripting/LayerKind.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This script demonstrates how to create a new layer and set its kind.

from appscript import app, k

# Start up Photoshop application
ps = app(id="com.adobe.Photoshop", terms="sdef")

strtRulerUnits = ps.settings.ruler_units()

if len(ps.documents()) < 1:
ps.settings.ruler_units.set(k.pixel_units)
docRef = ps.make(
new=k.document,
with_properties={
k.width: 320, k.height: 240, k.resolution: 72, k.mode: k.RGB, k.initial_fill: k.white
}
)
else:
docRef = ps.current_document()

layerRef = docRef.make(new=k.art_layer)
layerRef.kind.set(k.text_layer)
# Set the ruler back to where it was
ps.settings.ruler_units.set(strtRulerUnits)
24 changes: 24 additions & 0 deletions mac_scripting/LinkLayer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This scripts demonstrates how to link two layers.

from appscript import app, k

# Start up Photoshop application
ps = app(id="com.adobe.Photoshop", terms="sdef")

strtRulerUnits = ps.settings.ruler_units()

if len(ps.documents()) < 1:
ps.settings.ruler_units.set(k.pixel_units)
docRef = ps.make(new=k.document, with_properties={
k.width: 320, k.height: 240, k.resolution: 72, k.mode: k.RGB, k.initial_fill: k.white
}
)
else:
docRef = ps.current_document()

layerRef = docRef.make(new=k.art_layer)
layerRef2 = docRef.make(new=k.art_layer)
layerRef.link(with_=layerRef2)

# Set the ruler back to where it was
ps.settings.ruler_units.set(strtRulerUnits)
31 changes: 31 additions & 0 deletions mac_scripting/LoadSelection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# This script will demonstrate how to load a selection from a saved alpha channel.

from appscript import app, k

ps = app(id="com.adobe.Photoshop", terms="sdef")

strtRulerUnits = ps.settings.ruler_units()
ps.settings.ruler_units.set(k.pixel_units)

docRef = ps.make(new=k.document, with_properties={k.width: 320, k.height: 240})

# To save querying Photoshop for every width/height
# reference, it's faster to just store the values here
width, height = docRef.width(), docRef.height()

# Save a rectangular selection area offset by 50 pixels from the image border into an alpha channel
offset = 50
selBounds1 = ((offset, offset), (width - offset, offset), (width - offset, height - offset), (offset, height - offset))
docRef.select(region=selBounds1)
selAlpha = docRef.make(new=k.channel)
docRef.selection.store(into=selAlpha)

# Now create a second wider but less tall selection
selBounds2 = ((0, 75), (width, 75), (width, 150), (0, 150))
docRef.select(region=selBounds2)

# Load the selection from the just saved alpha channel, combining it with the active selection
docRef.selection.load(from_=selAlpha, combination_type=k.extended, inverting=False)

# Set ruler back to where it was
ps.settings.ruler_units.set(strtRulerUnits)
Loading

0 comments on commit 2a4456a

Please sign in to comment.