Copy link to clipboard
Copied
Hello,
I keep getting errors when creating a layer mask using photoshop JSX script
I'm looking for a way to loop through all the layers and add a layer mask at the size of the document canvas.
Here are the functions I am running but I can't figure out how to get it up and running
Thanks for your time
// loop through each layer
function walkLayers(o) {
var i;
var layer;
var frame;
var psd_name = decodeURI(app.activeDocument.name);
var file_name = psd_name.substring(0, psd_name.lastIndexOf('.')) || psd_name;
for (i = 0; i < o.layers.length; i++) {
layer = o.layers[i];
layer.name = file_name;
applyLayerMask(layer)
}
}
// Layer mask from selection
function applyLayerMask(layer) {
app.activeDocument.selection.selectAll(); // select entire canvas
// create a mask on layer
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
descriptor.putClass( s2t( "new" ), s2t( "channel" ));
reference.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "mask" ));
descriptor.putReference( s2t( "at" ), reference );
descriptor.putEnumerated( s2t( "using" ), c2t( "UsrM" ), s2t( "revealSelection" ));
executeAction( s2t( "make" ), descriptor, DialogModes.NO );
}
walkLayers(app.activeDocument);
I tried in version 2021 and 2024 and didn't get that error, however I didn't get the masks either.
This works for me, take from it what you like:
app.activeDocument.suspendHistory('Add reveal all layer mask to top-level layers...', 'maskAllLayers()');
function maskAllLayers() {
// Capture the initial layer visibility and layer selection
var currentLayersState = getLayersVisiblity();
// Ensure that a layer is selected
try {
activeDocument.activeLayer.link(activeDocument.activeL
...
Copy link to clipboard
Copied
I tried in version 2021 and 2024 and didn't get that error, however I didn't get the masks either.
This works for me, take from it what you like:
app.activeDocument.suspendHistory('Add reveal all layer mask to top-level layers...', 'maskAllLayers()');
function maskAllLayers() {
// Capture the initial layer visibility and layer selection
var currentLayersState = getLayersVisiblity();
// Ensure that a layer is selected
try {
activeDocument.activeLayer.link(activeDocument.activeLayer);
} catch (e) { }
// Loop over the root/top-level layers (change artLayers to layers to include groups)
for (var i = 0; i < app.activeDocument.artLayers.length; i++) {
app.activeDocument.activeLayer = activeDocument.artLayers[i];
// Ensure that the layer is not a background layer
if (!app.activeDocument.activeLayer.isBackgroundLayer) {
// Add a reveal all layer mask to the layer
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
descriptor.putClass(s2t("new"), s2t("channel"));
reference.putEnumerated(s2t("channel"), s2t("channel"), s2t("mask"));
descriptor.putReference(s2t("at"), reference);
descriptor.putEnumerated(s2t("using"), s2t("userMaskEnabled"), s2t("revealAll"));
executeAction(s2t("make"), descriptor, DialogModes.NO);
}
}
// Restore the initial layer visibility and selection
setLayersVisiblity(currentLayersState);
//// Functions ////
function getLayersVisiblity() {
// by jazz-y
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var targetLayers = executeActionGet(r).getList(p),
seletion = [],
visiblity = {};
for (var i = 0; i < targetLayers.count; i++) seletion.push(targetLayers.getReference(i).getIdentifier());
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var len = executeActionGet(r).getInteger(p);
for (var i = 1; i <= len; i++) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
r.putIndex(s2t('layer'), i);
if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
r.putIndex(s2t('layer'), i);
var id = executeActionGet(r).getInteger(p);
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
r.putIndex(s2t('layer'), i);
var visible = executeActionGet(r).getBoolean(p);
visiblity[id] = visible;
}
return {
selection: seletion,
visiblity: visiblity
};
}
function setLayersVisiblity(layersStateObject) {
// by jazz-y
var s2t = stringIDToTypeID;
for (var a in layersStateObject.visiblity) {
makeVisible = layersStateObject.visiblity[a] ? "show" : "hide";
(r = new ActionReference()).putIdentifier(s2t('layer'), a);
(d = new ActionDescriptor()).putReference(s2t('target'), r);
executeAction(s2t(makeVisible), d, DialogModes.NO);
}
if (layersStateObject.selection.length) {
var r = new ActionReference();
for (var i = 0; i < layersStateObject.selection.length; i++)
r.putIdentifier(s2t("layer"), layersStateObject.selection[i]);
(d = new ActionDescriptor()).putReference(s2t("target"), r);
d.putBoolean(s2t("makeVisible"), false);
executeAction(s2t("select"), d, DialogModes.NO);
} else {
(r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('target'), r);
executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
}
}
}
Copy link to clipboard
Copied
This is wild, thanks! I'm going to study this code, much appreciated
This JSX feature works awesome with Generate Image Assets plugin
Copy link to clipboard
Copied
I've adjusted the code a bit to check to see if there is a mask and if it doesn't apply mask to that layer
app.activeDocument.suspendHistory('Add reveal all layer mask to top-level layers...', 'setLayersWithMask()');
function setLayersWithMask() {
// Capture the initial layer visibility and layer selection
var currentLayersState = getLayersVisiblity();
// Ensure that a layer is selected
try {
activeDocument.activeLayer.link(activeDocument.activeLayer);
} catch (e) { }
// Loop over the root/top-level layers (change artLayers to layers to include groups)
for (var i = 0; i < app.activeDocument.artLayers.length; i++) {
app.activeDocument.activeLayer = activeDocument.artLayers[i];
if(!hasChannelMaskByName(app.activeDocument.layers[i].name)){
addMask();
}
}
function addMask(apply){
// by Stephen_A_Marsh
if (apply == undefined) apply = false;
try
{
// Add a reveal all layer mask to the layer
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
descriptor.putClass(s2t("new"), s2t("channel"));
reference.putEnumerated(s2t("channel"), s2t("channel"), s2t("mask"));
descriptor.putReference(s2t("at"), reference);
descriptor.putEnumerated(s2t("using"), s2t("userMaskEnabled"), s2t("revealAll"));
executeAction(s2t("make"), descriptor, DialogModes.NO);
return true
}
catch (e)
{
return false
}
}
/**
* deletes layer mask from active layer
* @Param if apply is true, mask will be applied, if false — mask will be discarded
* @Return boolean
*/
function deleteMask(apply)
{
if (apply == undefined) apply = false;
try
{
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), charIDToTypeID('Msk '));
desc.putReference(charIDToTypeID('null'), ref);
desc.putBoolean(charIDToTypeID('Aply'), apply);
executeAction(charIDToTypeID('Dlt '), desc, DialogModes.NO);
return true
}
catch (e)
{
return false
}
};
function hasChannelMaskByName( layerName ){
// by Michael_L_Hale
var ref = new ActionReference();
ref.putName( charIDToTypeID( "Lyr " ), layerName );
return executeActionGet( ref ).getBoolean( stringIDToTypeID( 'hasUserMask' ) );
}
// Restore the initial layer visibility and selection
setLayersVisiblity(currentLayersState);
//// Functions ////
function getLayersVisiblity() {
// by jazz-y
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var targetLayers = executeActionGet(r).getList(p),
seletion = [],
visiblity = {};
for (var i = 0; i < targetLayers.count; i++) seletion.push(targetLayers.getReference(i).getIdentifier());
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var len = executeActionGet(r).getInteger(p);
for (var i = 1; i <= len; i++) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
r.putIndex(s2t('layer'), i);
if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
r.putIndex(s2t('layer'), i);
var id = executeActionGet(r).getInteger(p);
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
r.putIndex(s2t('layer'), i);
var visible = executeActionGet(r).getBoolean(p);
visiblity[id] = visible;
}
return {
selection: seletion,
visiblity: visiblity
};
}
function setLayersVisiblity(layersStateObject) {
// by jazz-y
var s2t = stringIDToTypeID;
for (var a in layersStateObject.visiblity) {
makeVisible = layersStateObject.visiblity[a] ? "show" : "hide";
(r = new ActionReference()).putIdentifier(s2t('layer'), a);
(d = new ActionDescriptor()).putReference(s2t('target'), r);
executeAction(s2t(makeVisible), d, DialogModes.NO);
}
if (layersStateObject.selection.length) {
var r = new ActionReference();
for (var i = 0; i < layersStateObject.selection.length; i++)
r.putIdentifier(s2t("layer"), layersStateObject.selection[i]);
(d = new ActionDescriptor()).putReference(s2t("target"), r);
d.putBoolean(s2t("makeVisible"), false);
executeAction(s2t("select"), d, DialogModes.NO);
} else {
(r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('target'), r);
executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
}
}
}