Skip to main content
johnjoeparrot
Known Participant
November 6, 2024
Answered

PSD JSX - Loop through layers and apply layer mask to size of the document on each layer

  • November 6, 2024
  • 1 reply
  • 678 views

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);
This topic has been closed for replies.
Correct answer Stephen Marsh

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);
    }
  }

}

1 reply

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
November 7, 2024

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);
    }
  }

}
johnjoeparrot
Known Participant
November 7, 2024

This is wild, thanks! I'm going to study this code, much appreciated

This JSX feature works awesome with Generate Image Assets plugin