@gregd - How would the script know which of the three transparent areas should be selected? You mentioned arbitrary selection, so using a "random" operator?
As far as I know, multiple selections are just a single selection in scripting, at least in ExtendScript, I don't know about in UXP.
A selection can be converted to a path, with various degrees of accuracy. Unlike selections, paths are separate items that can be programmatically isolated from the overall collection.
So, I can envisage a script that loads all transparency as a selection, converts the selection to paths, which could then be used to individually isolate or select the pixels from the underlying area, based on the "approximate" path coordinates, but using the accuracy and fidelity of the pixels identified by the paths.
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-do-i-seperate-subjects-into-different-seperate-files-automatically/m-p/14449644#M782171
@gregd - This is what I was suggesting in my previous post:

/*
Random Selection from Transparent Layer.jsx
Stephen Marsh
v1.0 - 31st August 2025: Initial release
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-select-transparency-with-a-script/td-p/15481286
Based in part on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-do-i-seperate-subjects-into-different-seperate-files-automatically/td-p/14449644
*/
#target photoshop
(function () {
try {
if (!app.documents.length) {
alert("No documents are open.");
return;
}
// Check for pathItems and abort script if any are found
if (app.activeDocument.pathItems.length > 0) {
alert("Script aborted: Path items detected in the document.");
return;
}
app.activeDocument.suspendHistory("Random Selection from transparent layer", "main()");
} catch (e) {
alert("Error: " + e.message + " (Line: " + e.line + ")");
}
})();
// Main processing function
function main() {
var doc = app.activeDocument;
// Step 1: Duplicate active layer and prepare
doc.activeLayer.duplicate();
doc.activeLayer = doc.layers[0];
doc.activeLayer.name = "tempLayer";
// Step 2: Load layer transparency and expand selection
try {
app.activeDocument.selection.deselect();
} catch (e) { }
loadLayerTransparency();
doc.selection.invert();
doc.selection.expand(10);
// Step 3: Convert selection to work path and process
convertSelectionToWorkPath();
separateWorkPathIntoPaths();
// Remove the original work path
if (doc.pathItems.length > 0) {
doc.pathItems[0].remove();
}
// Step 4: Select random path and create selection
selectRandomNormalPath(doc);
convertPathToSelection();
deselectPaths();
// Step 5: Fill and cleanup
doc.selection.invert();
var fgColor = app.foregroundColor;
var bgColor = app.backgroundColor;
resetForegroundBackgroundColors();
fillWithForeground();
loadLayerTransparency();
doc.selection.invert();
doc.activeLayer.remove();
removePaths();
app.foregroundColor = fgColor;
app.backgroundColor = bgColor;
}
///// Helper functions /////
function loadLayerTransparency() {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));
desc.putReference(stringIDToTypeID("null"), ref);
var targetRef = new ActionReference();
targetRef.putEnumerated(
stringIDToTypeID("channel"),
stringIDToTypeID("channel"),
stringIDToTypeID("transparencyEnum")
);
desc.putReference(stringIDToTypeID("to"), targetRef);
executeAction(stringIDToTypeID("set"), desc, DialogModes.NO);
}
function convertSelectionToWorkPath() {
var desc = new ActionDescriptor();
var pathRef = new ActionReference();
pathRef.putClass(charIDToTypeID("Path"));
desc.putReference(charIDToTypeID("null"), pathRef);
var selectionRef = new ActionReference();
selectionRef.putProperty(charIDToTypeID("csel"), charIDToTypeID("fsel"));
desc.putReference(charIDToTypeID("From"), selectionRef);
desc.putUnitDouble(charIDToTypeID("Tlrn"), charIDToTypeID("#Pxl"), 2.0); // Set tolerance to 2 pixels
executeAction(charIDToTypeID("Mk "), desc, DialogModes.NO);
}
function separateWorkPathIntoPaths() {
if (!app.documents.length || !app.activeDocument.pathItems.length) {
return;
}
var doc = app.activeDocument;
var selectedPath = getSelectedPath();
if (!selectedPath) {
alert("No path selected");
return;
}
var pathData = extractPathData(doc, selectedPath);
// Create separate paths from each subpath
for (var i = 0; i < pathData.length; i++) {
var subPathArray = [pathData[i]]; // Wrap single subpath in array
var pathName = selectedPath.name + "_part_" + i;
createPathFromData(subPathArray, pathName);
}
}
function extractPathData(doc, path) {
var originalUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
try {
var ref = new ActionReference();
// Handle different path types
if (path.kind === PathKind.WORKPATH) {
ref.putProperty(charIDToTypeID("Path"), charIDToTypeID("WrPt"));
} else if (path.kind === PathKind.VECTORMASK) {
ref.putEnumerated(
charIDToTypeID("Path"),
charIDToTypeID("Path"),
stringIDToTypeID("vectorMask")
);
} else {
// Normal path - find its index
for (var i = 0; i < doc.pathItems.length; i++) {
if (doc.pathItems[i] === path) {
ref.putIndex(charIDToTypeID("Path"), i + 1);
break;
}
}
}
var desc = executeActionGet(ref);
var pathComponents = desc.getObjectValue(charIDToTypeID("PthC")).getList(stringIDToTypeID('pathComponents'));
var pathArray = [];
// Process each subpath
for (var i = 0; i < pathComponents.count; i++) {
var component = pathComponents.getObjectValue(i);
var subpathList = component.getList(stringIDToTypeID("subpathListKey"));
var operation = component.getEnumerationValue(stringIDToTypeID("shapeOperation"));
// Process each subpath in the component
for (var j = 0; j < subpathList.count; j++) {
var subPath = [];
var subpathObj = subpathList.getObjectValue(j);
var points = subpathObj.getList(stringIDToTypeID('points'));
var isClosed = false;
try {
isClosed = subpathObj.getBoolean(stringIDToTypeID("closedSubpath"));
} catch (e) { }
// Extract point data
for (var k = 0; k < points.count; k++) {
var pointObj = points.getObjectValue(k);
var anchorObj = pointObj.getObjectValue(stringIDToTypeID("anchor"));
var anchor = [
anchorObj.getUnitDoubleValue(stringIDToTypeID('horizontal')),
anchorObj.getUnitDoubleValue(stringIDToTypeID('vertical'))
];
var leftHandle = anchor;
var rightHandle = anchor;
var isSmooth = false;
try {
var leftObj = pointObj.getObjectValue(charIDToTypeID("Fwd "));
leftHandle = [
leftObj.getUnitDoubleValue(stringIDToTypeID('horizontal')),
leftObj.getUnitDoubleValue(stringIDToTypeID('vertical'))
];
} catch (e) { }
try {
var rightObj = pointObj.getObjectValue(charIDToTypeID("Bwd "));
rightHandle = [
rightObj.getUnitDoubleValue(stringIDToTypeID('horizontal')),
rightObj.getUnitDoubleValue(stringIDToTypeID('vertical'))
];
} catch (e) { }
try {
isSmooth = pointObj.getBoolean(charIDToTypeID("Smoo"));
} catch (e) { }
subPath.push([anchor, leftHandle, rightHandle, isSmooth]);
}
subPath.push(isClosed);
subPath.push(operation);
pathArray.push(subPath);
}
}
return pathArray;
} finally {
app.preferences.rulerUnits = originalUnits;
}
}
function createPathFromData(pathArray, pathName) {
var originalUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
try {
var desc = new ActionDescriptor();
var pathRef = new ActionReference();
pathRef.putProperty(charIDToTypeID('Path'), charIDToTypeID('WrPt'));
desc.putReference(stringIDToTypeID('null'), pathRef);
var componentList = new ActionList();
for (var i = 0; i < pathArray.length; i++) {
var subPath = pathArray[i];
var componentDesc = new ActionDescriptor();
var operation = subPath[subPath.length - 1];
var isClosed = subPath[subPath.length - 2];
componentDesc.putEnumerated(
stringIDToTypeID('shapeOperation'),
stringIDToTypeID('shapeOperation'),
operation
);
var subpathList = new ActionList();
var subpathDesc = new ActionDescriptor();
subpathDesc.putBoolean(charIDToTypeID('Clsp'), isClosed);
var pointsList = new ActionList();
// Add points (excluding the last two elements which are flags)
for (var j = 0; j < subPath.length - 2; j++) {
var point = subPath[j];
var pointDesc = new ActionDescriptor();
// Anchor point
var anchorDesc = new ActionDescriptor();
anchorDesc.putUnitDouble(charIDToTypeID('Hrzn'), charIDToTypeID('#Rlt'), point[0][0]);
anchorDesc.putUnitDouble(charIDToTypeID('Vrtc'), charIDToTypeID('#Rlt'), point[0][1]);
pointDesc.putObject(charIDToTypeID('Anch'), charIDToTypeID('Pnt '), anchorDesc);
// Forward handle
var forwardDesc = new ActionDescriptor();
forwardDesc.putUnitDouble(charIDToTypeID('Hrzn'), charIDToTypeID('#Rlt'), point[1][0]);
forwardDesc.putUnitDouble(charIDToTypeID('Vrtc'), charIDToTypeID('#Rlt'), point[1][1]);
pointDesc.putObject(charIDToTypeID('Fwd '), charIDToTypeID('Pnt '), forwardDesc);
// Backward handle
var backwardDesc = new ActionDescriptor();
backwardDesc.putUnitDouble(charIDToTypeID('Hrzn'), charIDToTypeID('#Rlt'), point[2][0]);
backwardDesc.putUnitDouble(charIDToTypeID('Vrtc'), charIDToTypeID('#Rlt'), point[2][1]);
pointDesc.putObject(charIDToTypeID('Bwd '), charIDToTypeID('Pnt '), backwardDesc);
// Smooth flag
pointDesc.putBoolean(charIDToTypeID('Smoo'), point[3]);
pointsList.putObject(charIDToTypeID('Pthp'), pointDesc);
}
subpathDesc.putList(charIDToTypeID('Pts '), pointsList);
subpathList.putObject(charIDToTypeID('Sbpl'), subpathDesc);
componentDesc.putList(charIDToTypeID('SbpL'), subpathList);
componentList.putObject(charIDToTypeID('PaCm'), componentDesc);
}
desc.putList(charIDToTypeID('T '), componentList);
executeAction(charIDToTypeID('setd'), desc, DialogModes.NO);
// Rename the work path
var doc = app.activeDocument;
for (var i = 0; i < doc.pathItems.length; i++) {
if (doc.pathItems[i].kind === PathKind.WORKPATH) {
doc.pathItems[i].name = pathName;
return doc.pathItems[i];
}
}
} finally {
app.preferences.rulerUnits = originalUnits;
}
return null;
}
function getSelectedPath() {
try {
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var desc = executeActionGet(ref);
var pathName = desc.getString(charIDToTypeID("PthN"));
var doc = app.activeDocument;
// Handle work path case
if (pathName === "Work Path") {
// Save work path first if it exists
if (doc.pathItems.length > 0 &&
doc.pathItems[doc.pathItems.length - 1].kind === PathKind.WORKPATH) {
saveWorkPath();
}
return doc.pathItems[doc.pathItems.length - 1];
} else {
return doc.pathItems.getByName(pathName);
}
} catch (e) {
return null;
}
}
function saveWorkPath() {
// Select work path
var selectDesc = new ActionDescriptor();
var selectRef = new ActionReference();
selectRef.putProperty(charIDToTypeID("Path"), charIDToTypeID("WrPt"));
selectDesc.putReference(charIDToTypeID("null"), selectRef);
executeAction(charIDToTypeID("slct"), selectDesc, DialogModes.NO);
// Create new path from work path
var createDesc = new ActionDescriptor();
var createRef = new ActionReference();
createRef.putClass(charIDToTypeID("Path"));
createDesc.putReference(charIDToTypeID("null"), createRef);
var fromRef = new ActionReference();
fromRef.putProperty(charIDToTypeID("Path"), charIDToTypeID("WrPt"));
createDesc.putReference(charIDToTypeID("From"), fromRef);
createDesc.putString(charIDToTypeID("Nm "), generateTimestamp());
executeAction(charIDToTypeID("Mk "), createDesc, DialogModes.NO);
}
function selectRandomNormalPath(doc) {
if (!doc || !doc.pathItems || doc.pathItems.length === 0) {
alert("No path items found.");
return null;
}
var normalPaths = [];
// Filter for normal paths only
for (var i = 0; i < doc.pathItems.length; i++) {
var path = doc.pathItems[i];
if (path.kind === PathKind.NORMALPATH) {
normalPaths.push(path);
}
}
if (normalPaths.length === 0) {
alert("No saved normal paths found.");
return null;
}
// Select random path
var randomIndex = Math.floor(Math.random() * normalPaths.length);
var selectedPath = normalPaths[randomIndex];
// Select the path using Action Manager
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putName(charIDToTypeID("Path"), selectedPath.name);
desc.putReference(charIDToTypeID("null"), ref);
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO);
return selectedPath;
}
function convertPathToSelection() {
var desc = new ActionDescriptor();
var selectionRef = new ActionReference();
selectionRef.putProperty(charIDToTypeID("Chnl"), charIDToTypeID("fsel"));
desc.putReference(charIDToTypeID("null"), selectionRef);
var pathRef = new ActionReference();
pathRef.putEnumerated(charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc.putReference(charIDToTypeID("T "), pathRef);
desc.putInteger(charIDToTypeID("Vrsn"), 1);
desc.putBoolean(stringIDToTypeID("vectorMaskParams"), true);
executeAction(charIDToTypeID("setd"), desc, DialogModes.NO);
}
function deselectPaths() {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc.putReference(charIDToTypeID("null"), ref);
executeAction(charIDToTypeID("Dslc"), desc, DialogModes.NO);
}
function resetForegroundBackgroundColors() {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(charIDToTypeID("Clr "), charIDToTypeID("Clrs"));
desc.putReference(charIDToTypeID("null"), ref);
executeAction(charIDToTypeID("Rset"), desc, DialogModes.NO);
}
function fillWithForeground() {
var desc = new ActionDescriptor();
desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("FlCn"), charIDToTypeID("FrgC"));
desc.putUnitDouble(charIDToTypeID("Opct"), charIDToTypeID("#Prc"), 100.0);
desc.putEnumerated(charIDToTypeID("Md "), charIDToTypeID("BlnM"), charIDToTypeID("Nrml"));
executeAction(charIDToTypeID("Fl "), desc, DialogModes.NO);
}
function generateTimestamp() {
var now = new Date();
var day = now.getDate();
var month = now.getMonth() + 1; // Month is 0-based
var year = now.getFullYear();
var hour = now.getHours();
var minutes = now.getMinutes();
var seconds = now.getSeconds();
return day + "-" + month + "-" + year + "_" + hour + "-" + minutes + "-" + seconds;
}
function removePaths() {
var doc = activeDocument;
var pLen = doc.pathItems.length;
var pArray = [];
for (var i = 0; i < pLen; i++) {
pArray.push(doc.pathItems[i].name);
}
for (var i = 0; i < pLen; i++) {
var curPath = doc.pathItems.getByName(pArray[i]);
curPath.remove();
}
}