1

I am working on a GIF animation script for Photoshop CS6 (it should also work for CC). One feature I want to add is removing fringing from each layer. I do this by making a layer mask followed by making a contracting selection modifier on the mask. Currently my script works, but it only applies this mask adjustment on the first layer. Is there a native way of running or recording specified actions to be applied on each layer of an opened document? I installed a script that does this but I don't want to call and run it externally in my script. My primary goal is to have everything consolidated into a single action script.

Using Xtoolkit, I have converted my recorded actions into a JSX script. Here is my unaltered version:

#target photoshop
//
// MakeLoopingGIF.jsx
//

//
// Generated Thu Apr 18 2019 01:31:08 GMT-0600
//

cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };

//
//==================== Make Looping GIF ==============
//

function MakeLoopingGIF() {
  // Delete
  function step1(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated(sTID("animationClass"), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('null'), ref1);
    executeAction(cTID('Dlt '), desc1, dialogMode);
  };

function RemoveFringe(){

  // Set
  function step2(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    var ref2 = new ActionReference();
    ref2.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Trsp'));
    ref2.putName(cTID('Lyr '), "Layer 1");
    desc1.putReference(cTID('T   '), ref2);
    executeAction(cTID('setd'), desc1, dialogMode);
  };

  var doc = app.activeDocument;
  // Make
  function step3(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    desc1.putClass(cTID('Nw  '), cTID('Chnl'));
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Msk '));
    desc1.putReference(cTID('At  '), ref1);
    desc1.putEnumerated(cTID('Usng'), cTID('UsrM'), cTID('RvlS'));
    executeAction(cTID('Mk  '), desc1, dialogMode);
  };

  // Set
  function step4(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    var ref2 = new ActionReference();
    ref2.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('T   '), ref2);
    executeAction(cTID('setd'), desc1, dialogMode);
  };

  // Contract
  function step5(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    desc1.putUnitDouble(cTID('By  '), cTID('#Pxl'), 1);
    executeAction(cTID('Cntc'), desc1, dialogMode);
  };

  // Inverse
  function step6(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    executeAction(cTID('Invs'), undefined, dialogMode);
  };

  // Delete
  function step7(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    executeAction(cTID('Dlt '), undefined, dialogMode);
  };

  // Set
  function step8(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    desc1.putEnumerated(cTID('T   '), cTID('Ordn'), cTID('None'));
    executeAction(cTID('setd'), desc1, dialogMode);
  };

  // Delete
  function step9(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('null'), ref1);
    desc1.putBoolean(cTID('Aply'), true);
    executeAction(cTID('Dlt '), desc1, dialogMode);
  };

  for (var i=0;i<doc.layers.length;i++){ 
    doc.activeLayer=doc.layers[i];
    RemoveFringe();// 
  };

  // Select All Layers
  function step10(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('null'), ref1);
    executeAction(sTID('selectAllLayers'), desc1, dialogMode);
  };

  // Duplicate
  function step11(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('null'), ref1);
    desc1.putInteger(cTID('Vrsn'), 5);
    executeAction(cTID('Dplc'), desc1, dialogMode);
  };

  // Reverse
  function step12(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('null'), ref1);
    executeAction(sTID('reverse'), desc1, dialogMode);
  };

  // Make Frames from Layers
  function step13(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    executeAction(sTID('animationFramesFromLayers'), desc1, dialogMode);
  };

  step1();      // Delete
  step2();      // Set
  step3();      // Make
  step4();      // Set
  step5();      // Contract
  step6();      // Inverse
  step7();      // Delete
  step8();      // Set
  step9();      // Delete
  step10();      // Select All Layers
  step11();      // Duplicate
  step12();      // Reverse
  step13();      // Make Frames from Layers
};

//=========================================
//                    MakeLoopingGIF.main
//=========================================
//

MakeLoopingGIF.main = function () {
  MakeLoopingGIF();
};

MakeLoopingGIF.main();

// EOF

"MakeLoopingGIF.jsx"
// EOF

Here is the layer mask method I need to loop for all layers in the active document:

function RemoveFringe(){

  // Set
  function step2(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    var ref2 = new ActionReference();
    ref2.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Trsp'));
    ref2.putName(cTID('Lyr '), "Layer 1");
    desc1.putReference(cTID('T   '), ref2);
    executeAction(cTID('setd'), desc1, dialogMode);
  };

  var doc = app.activeDocument;
  // Make
  function step3(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    desc1.putClass(cTID('Nw  '), cTID('Chnl'));
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Msk '));
    desc1.putReference(cTID('At  '), ref1);
    desc1.putEnumerated(cTID('Usng'), cTID('UsrM'), cTID('RvlS'));
    executeAction(cTID('Mk  '), desc1, dialogMode);
  };

  // Set
  function step4(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    var ref2 = new ActionReference();
    ref2.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('T   '), ref2);
    executeAction(cTID('setd'), desc1, dialogMode);
  };

  // Contract
  function step5(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    desc1.putUnitDouble(cTID('By  '), cTID('#Pxl'), 1);
    executeAction(cTID('Cntc'), desc1, dialogMode);
  };

  // Inverse
  function step6(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    executeAction(cTID('Invs'), undefined, dialogMode);
  };

  // Delete
  function step7(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    executeAction(cTID('Dlt '), undefined, dialogMode);
  };

  // Set
  function step8(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    desc1.putEnumerated(cTID('T   '), cTID('Ordn'), cTID('None'));
    executeAction(cTID('setd'), desc1, dialogMode);
  };

  // Delete
  function step9(enabled, withDialog) {
    if (enabled != undefined && !enabled)
      return;
    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('null'), ref1);
    desc1.putBoolean(cTID('Aply'), true);
    executeAction(cTID('Dlt '), desc1, dialogMode);
  };
  • try to add for loop for app.activeDocument.layers.length :) – Design Phoenix Apr 18 at 4:39
  • I've made everything via record actions @Design Phoenix. My action script is stored in the actions palette. I can convert it to JSX but I'd have no idea where to implement a for loop... – Mr. Mendelli Apr 18 at 4:42
  • used xbytors script or script evemt listener?You playing action right and not a script? – Design Phoenix Apr 18 at 4:53
  • All scripts I've created were done by recording actions. While I have Xtoolkit, I have only used certain tools and I do not currently know how to code scripts from scratch. – Mr. Mendelli Apr 18 at 4:57
  • Read my answer ; and if you have script then don't worry; just go to action; create new and add your script by Add Menu Item – Design Phoenix Apr 18 at 5:19
3

Your RemoveFringe() didn't have a closing bracket, plus none of the functions were called. Basically I stripped away the function definitions and just left the important bits:

for (var i = 0, l = activeDocument.layers.length; i < l; i++)
{
    activeDocument.activeLayer = activeDocument.layers[i];
    removeFringe();
};

function removeFringe()
{

    function cTID(s)
    {
        return app.charIDToTypeID(s);
    };

    function sTID(s)
    {
        return app.stringIDToTypeID(s);
    };

    // Set
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    var ref2 = new ActionReference();
    ref2.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Trsp'));
    ref2.putName(cTID('Lyr '), "Layer 1");
    desc1.putReference(cTID('T   '), ref2);
    executeAction(cTID('setd'), desc1, DialogModes.NO);

    // Make
    var desc1 = new ActionDescriptor();
    desc1.putClass(cTID('Nw  '), cTID('Chnl'));
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Msk '));
    desc1.putReference(cTID('At  '), ref1);
    desc1.putEnumerated(cTID('Usng'), cTID('UsrM'), cTID('RvlS'));
    executeAction(cTID('Mk  '), desc1, DialogModes.NO);

    // Set
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    var ref2 = new ActionReference();
    ref2.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('T   '), ref2);
    executeAction(cTID('setd'), desc1, DialogModes.NO);

    // Contract
    var desc1 = new ActionDescriptor();
    desc1.putUnitDouble(cTID('By  '), cTID('#Pxl'), 1);
    executeAction(cTID('Cntc'), desc1, DialogModes.NO);

    // Inverse
    executeAction(cTID('Invs'), undefined, DialogModes.NO);

    // Delete
    executeAction(cTID('Dlt '), undefined, DialogModes.NO);

    // Set
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putProperty(cTID('Chnl'), sTID("selection"));
    desc1.putReference(cTID('null'), ref1);
    desc1.putEnumerated(cTID('T   '), cTID('Ordn'), cTID('None'));
    executeAction(cTID('setd'), desc1, DialogModes.NO);

    // Delete
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
    desc1.putReference(cTID('null'), ref1);
    desc1.putBoolean(cTID('Aply'), true);
    executeAction(cTID('Dlt '), desc1, DialogModes.NO);
};
  • same here; i added whole auto generated code into function and then looped it; let's just hope it works since i can't test it on my GIF! – Design Phoenix Apr 18 at 8:21
  • Thank you for your answer! Your code doesn't crash upon launch like mine did, but it does lockup Photoshop completely at some point. It looks like it's doing the tasks I want correctly, but I think it's doing too much now. Did you loop the whole script or just the layer masking method? Photoshop is behaving like it can't handle the workload and my RAM spikes when Photoshop freezes with the new script. – Mr. Mendelli Apr 18 at 8:33
  • @Mr.Mendelli, If your layer count is high (upwards from ~400), PS will become unresponsive but should power through eventually... Even if the script does nothing but selects a layer and moves on... – Joonas Apr 18 at 8:40
  • The script loops through the whole script (whole action) because I don't know what bits you need and what bits you don't :) that's why I asked to only leave relevant code in your example. So yes, if you have a lot of layers it could take some time. – Sergey Kritskiy Apr 18 at 8:41
  • 1
    go with @SergeyKritskiy answer :) it's cleaned; I'm removing my answer :D – Design Phoenix Apr 18 at 9:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.