jazz-y
Guide
jazz-y
Guide
Activity
Apr 02, 2023
12:01 PM
@QPR John, reports of such problems are rare in the community.
... View more
Apr 02, 2023
02:46 AM
Have you done a clean install of windows 11 or an upgrade? If it's an update, try uninstalling and reinstalling Photoshop. It is possible that during the upgrade process the objects required for VB ScriptingSupport to work were not re-registered in the operating system.
... View more
Mar 30, 2023
10:32 PM
1 Upvote
You are writing code using ExtendScript and the Photoshop Object Model while trying to run it in the UXP Developer Tool which works with the Photoshop UXP API. This is are different scripting systems.
You can read more about UXP object models here: Photoshop API
You can also use the ExtendScript debugger for VSCode to work with the code you wrote (ExtendScript)
... View more
Mar 30, 2023
09:16 AM
1 Upvote
Unfortunately in the latest version of Photoshop there is a bug with the inability to execute the save command in the action. We all hope to update and fix this bug soon.
Workaround: since you only have 2 commands, shorten the action to one - close (you can confirm saving when close the file). This will work.
... View more
Mar 29, 2023
01:30 PM
You can't change Photoshop's standard panels, but you can write a new panel with the functionality you need.
There is a workaround - you can write a separate action that will run the script. In this case, the script will do what you need. Not sure if UXP scripts support writing to actions, but it is possible with old *.jsx scripts.
... View more
Mar 29, 2023
01:28 PM
This is a bug in the latest version of Photoshop. The Save command written to the action causes an error. We all hope that it will be quickly fixed and a new update will be released.
At the moment, I recommend installing the previous version (24.2.1) of Photoshop. Don't forget to save your actions, keyboard shortcuts, workspaces to disk so that you don't lose access to them when you upgrade to a previous version.
... View more
Mar 29, 2023
01:26 PM
3 Upvotes
*.jsx are scripts written in ExtendScript, an old scripting engine
UXP is a new technology and is not compatible with older ExtendScripts
You must save your code to *.psjs file (UXP script standalone) and run it via File > Scripts > Browse... (drag and drop is not supported yet)
you can read more here: UXP Scripting in Photoshop
... View more
Mar 29, 2023
01:13 PM
2 Upvotes
const reverseOrder = false; // true - layers pass from top to bottom, false - from bottom to top
var s2t = stringIDToTypeID,
layerMasks = [];
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('hasBackgroundLayer'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var offset = executeActionGet(r).getBoolean(p) ? 1 : 0;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var to = executeActionGet(r).getInteger(p);
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('itemIndex'));
r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
var activeLayer = executeActionGet(r).getInteger(p) - offset;
for (var i = 1; i <= to; i++) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerKind'));
r.putIndex(s2t('layer'), i);
if (executeActionGet(r).getInteger(p) != 13) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('hasUserMask'));
r.putIndex(s2t('layer'), i);
if (executeActionGet(r).getBoolean(p)) layerMasks.push(i)
}
}
if (reverseOrder) layerMasks.reverse()
var i = 0;
if (layerMasks.length) {
do {
if (i == layerMasks.length) { i = 0; activeLayer = reverseOrder ? to + 1 : 0 }
if (reverseOrder ? layerMasks[i] < activeLayer : layerMasks[i] > activeLayer) { activeLayer = layerMasks[i]; break; }
i++
} while (true)
(r = new ActionReference()).putIndex(s2t("layer"), activeLayer);
(d = new ActionDescriptor()).putReference(s2t("target"), r)
executeAction(s2t("select"), d, DialogModes.NO);
(r = new ActionReference()).putEnumerated(s2t("channel"), s2t('channel'), s2t('mask'));
(d = new ActionDescriptor()).putReference(s2t('target'), r);
executeAction(s2t('select'), d, DialogModes.NO);
}
... View more
Mar 29, 2023
04:55 AM
Try to make all functions synchronous
function getSelectedAction() {
const batchPlay = require('photoshop').action.batchPlay;
const result = batchPlay(
[
{
"_obj": "get",
"_target": [
{
_ref: "action", _enum: "ordinal", _value: "targetEnum"
}
],
"_options": {
"dialogOptions": "dontDisplay"
}
}
],
{
"synchronousExecution": true
}
);
const selectedAction = {
selectedAction: result[0].name,
selectedActionSet: result[0].parentName
};
return selectedAction;
}
try {
const selectedAction = getSelectedAction();
console.log('Selected action:', selectedAction);
} catch (error) {
console.error('Error:', error);
}
In any case, I would advise you to visit the community creativeclouddeveloper.com which is focused on UXP
... View more
Mar 29, 2023
04:11 AM
Спасибо! Я уже накидал свой вариант, но, конечно, в более сокращенном виде 🙂
This code is only suitable for RGB:
const AVERAGE_AREA = 51;
var startRulerUnits = app.preferences.rulerUnits,
startTypeUnits = app.preferences.typeUnits;
app.preferences.rulerUnits = Units.PIXELS
app.preferences.typeUnits = TypeUnits.PIXELS
var doc = activeDocument,
colorSampler = activeDocument.colorSamplers[0],
x = colorSampler.position[0].value,
y = colorSampler.position[1].value;
var selRegion = [
[x - AVERAGE_AREA / 2, y - AVERAGE_AREA / 2],
[x + AVERAGE_AREA / 2, y - AVERAGE_AREA / 2],
[x + AVERAGE_AREA / 2, y + AVERAGE_AREA / 2],
[x - AVERAGE_AREA / 2, y + AVERAGE_AREA / 2]
]
doc.selection.select(selRegion)
var mean= [],
color = new SolidColor;
for (var i = 0; i < doc.channels.length; i++) {
var n = p = 0,
cur = doc.channels[i].histogram;
for (var x = 0; x < cur.length; x++) {
n += cur[x]
p += cur[x] * x
}
mean.push(p / n)
}
doc.selection.deselect()
with (color.rgb) { red = mean[0]; green = mean[1]; blue = mean[2]; };
var readColorHue = Math.round(color.hsb.hue)
var readColorSaturation = Math.round(color.hsb.saturation)
var readColorBrightness = Math.round(color.hsb.brightness)
alert('H ' + readColorHue + ' S ' + readColorSaturation + ' B ' + readColorBrightness)
app.preferences.rulerUnits = startRulerUnits
app.preferences.typeUnits = startTypeUnits
@r-bin proposed a similar solution to this problem, but it is more complete and faster. At the link above you will find a function that changes app.foregroundColor to the color at the given point. You can get the coordinates of this point from the .position property of the colorSampler. After that, you need to create a selection by sequentially describing the coordinates of the selection points (note that @r-bin shifts the coordinates to the right down from the desired point by 1 pixel, you need to rewrite the code so that the point you need is in the center of the selection). Further, everything is simple - after executing the function, you just need to read the color value of app.foregroundColor
... View more
Mar 29, 2023
02:59 AM
No. AM code also shows 1x1 pixel color value
A workaround is needed here. The problem is that blur filters includes pixels outside the selection for averaging. Perhaps the Custom filter would help here, but I don’t know how to use matrices at all, maybe the @r-bin will help.
The simplest thing that comes to mind is to find the point where the Color Sampler is set, create a selection of the desired size, read and average the information about the colors of the pixels from the histogram. However, I am also not at the computer right now to check how the result will match the information panel.
... View more
Mar 29, 2023
02:18 AM
3 Upvotes
I wanted to lead you to the idea that mixing DOM and AM code is not a good idea. DOM objects often have attributes that are similar to AM, but carry a completely different meaning. In your code, you use indexes from the activeDocument.layers collection, hoping that it will coincide with the indexing order in AM, however, in AM, indexing of layers is end-to-end within the document (counting from bottom to top) plus it contains indexes of hidden elements (closing sections of groups), in the DOM, layer indexing goes at the level of the current parent element, starts from top to bottom and does not contain indexes of hidden elements.
Basically I write the code by hand. It took me a couple of years to learn and memorize frequently used objects and functions. When it comes to something unfamiliar, I use either scriptListener or app.notifiers (in the latter case, I can immediately get a ready-made descriptor and study it in a way that suits me)
I often reuse code. I have an object template with basic functions for getting and setting parameters, in which I usually put the functions necessary for the operation of a particular script, something like in this topic: .jsx script extremely slow If necessary, I combine some functions and make them dependent on the properties of the parent object (for example, you can activate, delete a layer, document, channel, path with the same function, simply by changing the name of the object class and the name of the action).
I don't like compiling code into one big library because I try to make every script clean of dependencies. In general, I am an ordinary photographer and writing scripts is nothing more than a hobby. You can learn a lot from @xbytor2 xtools, he did a great job putting together a lot of features. Many of the things he did are still beyond my comprehension.
... View more
Mar 28, 2023
02:44 PM
The frame tool can help you (with the resize during place option set in the Photoshop settings). The only condition is that the image you are dragging must be equal to or larger than the size of the frame.
... View more
Mar 28, 2023
02:22 PM
Color replacement tool works in one of four color replacement modes - color, luminosity, saturation, hue. Apparently your shapes slightly differ in lightness. When you work with the Color replacement tool in color mode, it actually changes the color, but it keeps the object's original lightness. You need to either additionally go over it with the Color replacement tool in luminosity mode
or lock the transparency of the layer and change the color of the object using the paintbrush tool (if the shape is on a separate layer and is bounded by transparency)
... View more
Mar 28, 2023
02:14 PM
@Lkiia wrote:
To match the color, I used the eyedropper tool, picked color on the left pic, and then switched to the layer of the right pic
From your description it is not entirely clear whether the objects are in the same document or in different ones at the time of color transfer?
... View more
Mar 28, 2023
09:39 AM
1 Upvote
Good! Now test your code on these files:
Test1.psd has 7 invisible layers.
Test2.psd has 5 invisible layers (note - the visibility of the background layer is turned off)
Would it be that easy to change your code to get the right answer? 🤔
* initially my ActionManager code didn't take groups into account, because I just wanted to demonstrate the difference in execution time, now I've fixed it
** i just want to push you to certain conclusions
$.hiresTimer
var s2t = stringIDToTypeID;
invisible = layerCount = 0;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('hasBackgroundLayer'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var from = executeActionGet(r).getBoolean(p) ? 0 : 1;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var to= executeActionGet(r).getInteger(p);
for (var i = from; i <= to; i++) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerKind'));
r.putIndex(s2t('layer'), i);
if (executeActionGet(r).getInteger(p) != 13){
layerCount++
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
r.putIndex(s2t('layer'), i);
if (!executeActionGet(r).getBoolean(p)) invisible++
}
}
alert ('Total layers: ' + layerCount +'\nInvisible layers: ' + invisible +'\nTimer: ' + Number($.hiresTimer)/1000000+ 's')
... View more
Mar 28, 2023
08:37 AM
2 Upvotes
@jefbr, remove background layer from the document and run your code again 😉
... View more
Mar 28, 2023
06:59 AM
3 Upvotes
I would say this - if you study the ActionManager (or its upgraded version of batchPlay (UXP)) sufficiently, then there will be no desire to return to DOM objects. I usually only use the DOM for basic functionality related to interacting with the application.
A simple example: a 1x1px file with 601 layers (including background) is attached to a post. Let's say we need to count how many invisible layers are in this document:
DOM code:
$.hiresTimer
var doc = activeDocument,
invisible = 0;
for (var i=0; i<doc.layers.length;i++) if (!doc.layers[i].visible) invisible++
alert ('Total layers: ' + i +'\nInvisible layers: ' + invisible +'\nTimer: ' + Number($.hiresTimer)/1000000+ 's')
Result:
ActionManager code:
$.hiresTimer
var s2t = stringIDToTypeID;
invisible = 0;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('hasBackgroundLayer'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var from = executeActionGet(r).getBoolean(p) ? 0 : 1;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var to= executeActionGet(r).getInteger(p);
for (var i = from; i <= to; i++) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
r.putIndex(s2t('layer'), i);
if (!executeActionGet(r).getBoolean(p)) invisible++
}
alert ('Total layers: ' + (to + !from) + '\nInvisible layers: ' + invisible +'\nTimer: ' + Number($.hiresTimer)/1000000+ 's')
Result:
... View more
Mar 28, 2023
04:12 AM
4 Upvotes
In both cases, you are dealing with javascript (more precisely, with its variant extendScript).
The first example is the Photoshop Object Model (DOM), the second example is ActionManger code.
The DOM is well documented, however it doesn't fully cover all of Photoshop's automation capabilities. ActionManger has no documentation, it's essentially an internal action language. But with it, you can perform a significantly larger number of operations than with the help of DOM.
ActionManger code typically runs faster or at the same speed as DOM.
Both options have compatibility issues with past versions of Photoshop.
ActionManger is of interest when you need to do something that can't be done with regular DOM functions.
... View more
Mar 28, 2023
12:41 AM
1 Upvote
Where did you find that you can get the name of the active action using the "selected" property? 🤔
async function getSelectedAction() {
const batchPlay = require('photoshop').action.batchPlay;
const result = await batchPlay(
[
{
"_obj": "get",
"_target": [
{
_ref: "action", _enum: "ordinal", _value: "targetEnum"
}
],
"_options": {
"dialogOptions": "dontDisplay"
}
}
],
{
"synchronousExecution": true
}
);
const selectedAction = {
selectedAction: result[0].name,
selectedActionSet: result[0].parentName
};
return selectedAction;
}
(async () => {
try {
const selectedAction = await getSelectedAction();
console.log('Selected action:', selectedAction);
} catch (error) {
console.error('Error:', error);
}
})();
* it should be understood that there are several border states that need to be taken into account and processed separately: a) if an ActionSet is selected, b) if a command inside an action is selected.
... View more
Mar 27, 2023
10:34 AM
Istall ExtendScript Debugger, this will allow you to run and debug *.jsx scripts in VS Code.
... View more
Mar 27, 2023
01:28 AM
2 Upvotes
Explain in more detail where you are trying to run this code?
Your code looks like Extend Script (*.jsx). Save it as a separate text file, change the extension to *.jsx and try dragging it into Photoshop (or use menu File -> Sripts -> browse)
If we are talking about UXP Developer Tools, then it is quite logical that you get errors - there is a different structure of DOM objects. Read about it here:Photoshop API
... View more
Mar 27, 2023
12:02 AM
In Windows, you can press Win+R, enter the path %userprofile%\AppData\Roaming\adobe and confirm.
A directory with Adobe application settings will open, among which you can see folders with the current and previous versions of Photoshop (there you can find settings for hotkeys, workspaces, etc.). However, you will not see the actions there: if you did not take care to save them to disk in advance, then they are stored in the current Photoshop settings file: Adobe Photoshop Prefs.psp (and extracting them from there is a difficult task).
If you haven't uninstalled the current version yet, you can save your actions to disk:
and then load them to the previous version.
... View more
Mar 26, 2023
11:20 PM
1 Upvote
@Bojan Živković, using actions, we can create a copy of the mask in the way i described (in one command). As we can see from the parameters, the mask of another layer is assigned to the current layer. The only condition is that before copying, you need to select the target layer (without a mask).
we can also create a new mask on the target layer and copy the existing mask using the Apply Image command:
... View more
Mar 26, 2023
01:36 PM
Click once on the mask on the layer to make it active. Hold alt key and drag to the desired layer.
... View more
Mar 26, 2023
01:19 PM
1 Upvote
There are several community reports about a problem with saving through an action command in the latest version of Photoshop. This is probably a bug.
Changing the save settings, overwriting the operation in the action, resetting Photoshop settings do not help. If your automation script expects the file to be closed after saving, you can remove the save step and use the close command (with "save changes" specified). If this way does not suit you, I recommend temporarily installing the previous version 24.2.1 and waiting for the next update.
... View more
Mar 25, 2023
02:37 PM
1 Upvote
I re-read this thread over and over again. It seems to me that we have not come close to understanding the @heroleam's task.
1 cm2 at a resolution of 600 pixels/cm contains 360,000 pixels. This is an objective reality. In the table, we see approximately the same value - 359400, perhaps this is due to the fact that for a printing device 1 pixel is not equal to 1 point (that is, the resolution of the printing device is slightly less than the resolution of the file).
Why do we need to know how many pixels Photoshop shows in 1 cm2, taking into account caching, if we can accurately calculate the number of pixels using the original script!?
Perhaps @heroleam needs to know not the TOTAL number of pixels in the selection, but only the number of BLACK pixels? In this case, it is enough to modify the script as follows:
#target photoshop
// Get the current Photoshop document
var doc = app.activeDocument;
// Get the brightness (Y) channel of the image
var channel = doc.activeChannels[0];
// Get the histogram of the luminosity channel
var histogram = channel.histogram;
// Copy the value to the clipboard
var d = new ActionDescriptor();
d.putString(stringIDToTypeID("textData"), histogram[0]);
executeAction(stringIDToTypeID("textToClipboard"), d, DialogModes.NO);
// Show an alert
alert("Black pixels: " + histogram[0]);
(the original script that the author generated via chatGPT calculates the sum of ALL pixels, both black and non-black)
... View more
Mar 25, 2023
04:30 AM
I cannot reproduce your issue.
Tried including app.preferences.displayDialogs = DialogModes.ALL, tried different units (by the way, activeDocument.width.as('px') doesn't work if percentages are used as rulerUnits), never saw any dialog other than scale alert.
... View more
Mar 25, 2023
01:02 AM
3 Upvotes
In InDesing and Illustrator, linked files are embedded at the document level. In Photoshop, the nesting system is much more complicated - we can create a smart object inside which there will be a linked file, inside this linked file there will be another smart object with linked files inside, and so on. That is, linked objects in Photoshop are rather not part of the document, but part of the layer.
Try this script. It checks for files that need to be updated at the first level (without going deep into the linked files and smart objects themselves):
/**
* Is there a way to alert when there's modified content like in InDesign?
* https://community.adobe.com/t5/photoshop-ecosystem-discussions/is-there-a-way-to-alert-when-there-s-modified-content-like-in-indesign/td-p/13678234
*/
#target photoshop
var apl = new AM('application'),
doc = new AM('document'),
lr = new AM('layer');
if (apl.getProperty('numberOfDocuments')) {
if (doc.hasProperty('numberOfLayers')) {
var len = doc.getProperty('numberOfLayers');
linkedObjects = [];
for (var i = 1; i <= len; i++) {
if (lr.getProperty('layerSection', i, true).value == 'layerSectionEnd') continue;
if (lr.getProperty('layerKind', i, true) == 5) {
var smartObject = doc.descToObject(lr.getProperty('smartObject', i, true).value)
if (smartObject.linked) {
if (smartObject.linkChanged) {
var cur =
{
layerID: lr.getProperty('layerID', i, true),
link: !(smartObject.link instanceof File) ? smartObject.fileReference : File(smartObject.link)
}
var copyOfLayer = false;
for (var x = 0; x < linkedObjects.length; x++) {
if (decodeURI(cur.link).toUpperCase() == decodeURI(linkedObjects[x].link).toUpperCase()) {
copyOfLayer = true
break;
}
}
if (!copyOfLayer) linkedObjects.push(cur)
}
}
}
}
if (linkedObjects.length) showDialog(linkedObjects)
}
}
function showDialog(fileList) {
var w = new Window("dialog {text: 'List of modified links'}"),
l = w.add("listbox", [0, 0, 600, 400], undefined, { multiselect: true }),
gButtons = w.add("group"),
bnOk = gButtons.add("button {text:'Update all files'}", [0, 0, 150, -1], undefined, { name: "ok" }),
bnCancel = gButtons.add("button {text:'Cancel'}", undefined, undefined, { name: "cancel" });
l.graphics.font = "dialog:12";
bnOk.onClick = function () {
w.close();
var ids = [];
if (l.selection != null) {
for (var i = 0; i < l.items.length; i++)
if (l.items[i].selected) ids.push(fileList[i].layerID)
}
doc.updateLinks(ids)
}
l.onClick = function () {
bnOk.text = 'Update ' + (l.selection == null ? 'all' : 'seleted (' + l.selection.length + ')')
}
w.onShow = function () {
for (var i = 0; i < fileList.length; i++) l.add('item', fileList[i].link instanceof File ? fileList[i].link.fsName : fileList[i].link)
}
w.show()
}
function AM(target) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.hasProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
try { return executeActionGet(r).hasKey(property) } catch (e) { return false }
}
this.descToObject = function (d, o) {
o = o ? o : {}
for (var i = 0; i < d.count; i++) {
var k = d.getKey(i)
o[t2s(k)] = getDescValue(d, k)
}
return o
}
this.selectLayerByIDList = function (IDList) {
var ref = new ActionReference()
for (var i = 0; i < IDList.length; i++) {
ref.putIdentifier(s2t("layer"), IDList[i])
}
var desc = new ActionDescriptor()
desc.putReference(s2t("target"), ref)
desc.putBoolean(s2t("makeVisible"), false)
executeAction(s2t("select"), desc, DialogModes.NO)
}
this.updateLinks = function (ids) {
if (ids.length) {
for (var i = 0; i < ids.length; i++) {
var r = new ActionReference();
r.putIdentifier(s2t('layer'), ids[i]);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);
executeAction(s2t("placedLayerUpdateModified"), d, DialogModes.NO);
}
} else {
executeAction(s2t("placedLayerUpdateAllModified"), new ActionDescriptor(), DialogModes.NO);
}
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
}
* using the File -> Scripts -> Script event manager you can add this script to the "open document" event (and it will check the content every time any document is opened)
... View more
Mar 24, 2023
11:41 PM
3 Upvotes
try this:
#target photoshop
activeDocument.suspendHistory('Divide by selection', 'main()')
function main() {
var doc = new AM('document'),
lr = new AM('layer'),
pth = new AM('path'),
targetLayer = lr.getProperty('layerID');
if (doc.hasProperty('selection')) lr.makePathFromSelection(2);
if (doc.getProperty('numberOfPaths')) {
var pathContents = pth.getProperty('pathContents').value.getList(stringIDToTypeID('pathComponents'))
for (var i = 0; i < pathContents.count; i++) {
pth.makePathFromSubpath(pathContents.getObjectValue(i))
pth.makeSelectionFromPath()
lr.select(targetLayer);
lr.cutToLayer();
}
lr.select(targetLayer)
lr.clearSelection()
pth.delete()
}
}
function AM(target, order) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.hasProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
return executeActionGet(r).hasKey(property)
}
this.select = function (id) {
var r = new ActionReference();
if (typeof id == 'number') r.putIdentifier(target, id) else r.putName(target, id);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);
}
this.makeSelectionFromPath = function () {
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(r1 = new ActionReference()).putProperty(s2t('path'), s2t('workPath'));
d.putReference(s2t('to'), r1);
d.putBoolean(s2t('vectorMaskParams'), true);
executeAction(s2t('set'), d, DialogModes.NO);
}
this.deleteCurrentPath = function () {
(r = new ActionReference()).putProperty(s2t('path'), s2t('workPath'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('delete'), d, DialogModes.NO);
}
this.makePathFromSelection = function (tolerance) {
tolerance = tolerance ? tolerance : 10;
(r = new ActionReference()).putClass(s2t('path'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(r1 = new ActionReference()).putProperty(s2t('selectionClass'), s2t('selection'));
d.putReference(s2t('from'), r1);
d.putUnitDouble(s2t('tolerance'), s2t('pixelsUnit'), tolerance);
executeAction(s2t('make'), d, DialogModes.NO);
}
this.makePathFromSubpath = function (pth) {
(r = new ActionReference()).putProperty(stringIDToTypeID("path"), stringIDToTypeID("workPath"));
(d = new ActionDescriptor()).putReference(stringIDToTypeID("null"), r);
(l = new ActionList()).putObject(stringIDToTypeID("pathComponent"), pth);
d.putList(stringIDToTypeID("to"), l);
executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
}
this.clearSelection = function () {
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putEnumerated(s2t('to'), s2t('ordinal'), s2t('none'));
executeAction(s2t('set'), d, DialogModes.NO);
}
this.delete = function (name) {
var r = new ActionReference();
if (name) r.putName(target, name) else r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('delete'), d, DialogModes.NO);
}
this.cutToLayer = function () {
executeAction(s2t('cutToLayer'), undefined, DialogModes.NO);
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
}
* intsead of selection, you can draw a crop zone with the pen tool - every closed path will be copied.
... View more