7 Replies Latest reply on Jun 23, 2012 3:54 PM by jacobolus

    How to manipulate layer masks in ExtendScript?

    mrcalph

      I'm referencing this previous discussion (circa 2008, 4 years ago) regarding layer mask manipulation in ExtendScript:

      http://forums.adobe.com/message/1890037#1890037

       

      1. Is this still the only way to create a layer mask?

      2. Regarding the first, where do I find documentation on the esoteric looking "CharIdToTypeId" methods?

       

      Thank you

        • 1. Re: How to manipulate layer masks in ExtendScript?
          mrcalph Level 1

          Not sure if this entirely completes my answer, but til about the Scripting Listener plug-in. That just might make things a lot "simpler".

          • 2. Re: How to manipulate layer masks in ExtendScript?
            mrcalph Level 1

            So using the original posting and some Scripting Listener tests, I still have a couple questions:

            1. Where is the documentation for all the different charIdToTypeId names?

                 - The following contains event codes, but not target codes, or others: http://cssdk.host.adobe.com/sdk/1.0/docs/WebHelp/app_notes/photoshop.htm

            2. How do I make a layer active in Javascript? (Since making a layer mask in that incredibly convoluted script produced by the Scripting Listener plug-in works on the "current" active layer.) (Apparently Document.activeLayer is a writable property. I'd still like to know how to add a mask to a layer that is not "active".)

            • 3. Re: How to manipulate layer masks in ExtendScript?
              dgolberg Level 1

              To answer #2; making a layer active, you must first know what layer you wish to make active.  The easiest way requires that you know the name of the layer and search for that.  See below:

               

              var myDoc = app.activeDocument; //Alternatively: var myDoc = app.documents.getByName("docName.psd"); to find the document named "docName.psd" if multiple docs are open
              var myLayer = myDoc.layers.getByName("targetLayer"); //Finds the layer named targetLayer if it's not in any groups
              myDoc.activeLayer = myLayer; //Make the layer the active layer
              

               

              If your layer is within a group, you'll have to check inside that group, which can be done by changing the second line above to:

               

              var myLayer = myDoc.layerSets.getByName("groupName").layers.getByName("targetLayer");
              

               

              To find a layer regardless of what group it is in, things get a little complex.  You'll have to, first, find all the groups (photoshop script calls them "layerSets") in the root of the document.  You'll then be able to search those groups for any additional groups and sub-groups within to an infinite extent.

               

              #target photoshop
              var myDoc = app.activeDocument;
              main();
              
              function main() {
                  var groups = [];
                  /////////Find Your Base Groups/////////
                  for(var z=0;z<myDoc.layers.length;z++) { //Cycle through all the layers in the document
                      if(myDoc.layers[z].layerSets) { //Determine if it is a group or not
                          groups.push(myDoc.layers[z]); //Add the layer to the "groups" array if it is, in fact, a group
                      }
                  }
                  ////////Find All Sub-Groups//////////
                  for(var z=0;z<groups.length;z++) { //Cycle through all the groups in the "groups" array
                      for(var e=0;e<groups[z].layers.length;e++) { //Cycle through the layers in the current group
                          if(groups[z].layers[e].layerSets) { //Determine if layer is a group or not
                              groups.push(groups[z].layers[e]); //Add the layer to the "groups" array if it is, in fact, a group
                          }
                      }
                  }
                  /////////Look for Your Layer//////////
                  var foundLayer = null;
                  for(var z in groups) { //Cycle through the list of groups and sub-groups we created earlier
                      try {
                          foundLayer = groups[z].layers.getByName("targetLayer"); //Change the "foundLayer" variable to the target layer if it exists in the current group of this loop cycle
                          break; //Stop the loop if the layer is found
                      } catch(e) {}
                  }
                  /////////Determine if the layer was found////////
                  if(foundLayer != null) {
                      myDoc.activeLayer = foundLayer; //Make the layer active if it's found
                      //run your script here (recommend placing it in another function and calling the function here instead).
                  } else {
                      alert("The layer could not be found!"); //Alert if the layer could not be found
                  }
              }
              

               

              The downside to the above method is, it can take a long time to run if you have a large number of groups and layers.  There may be a more efficient way to do it than that, but that's the best way I know of.  Anyway, I'm starting to stray beyond the scope of the original question.  I hope this helps you out some at least.  I know it doesn't answer your question in the topic line, but hopefully it answers your other one (and probably then-some).

               

              As far as manipulating layer masks; your best bet IS likely going to be the script listener code.  Simply enable the plug-in, manually do whatever it is you need the script to do; then copy the code for that action to a separate function and name the function based on what it does.  You can  usually tell what part of the scriptListener code is changeable (if any is), so you can easily change that to a variable in order to change it based on what you want it to do/affect if it's called multiple times throughout the script.  Anyway, if you have any other questions, or need me to clarify anything, let me know.

               

              dgolberg

              1 person found this helpful
              • 4. Re: How to manipulate layer masks in ExtendScript?
                mrcalph Level 1

                Do you know how to make an ActionReference for a specific layer? All of the ScriptingListener output impies currently active layer. Getting the layer programmatically is not the issue, nor is making it active. Or is it because there is not "scripting api" for the layer mask that it has to be performed on the document's currently active layer?

                • 5. Re: How to manipulate layer masks in ExtendScript?
                  dgolberg Level 1

                  That would be correct.  Unless there is something I have not yet found, you can only perform layer mask operations on the currently active layer.

                  • 6. Re: How to manipulate layer masks in ExtendScript?
                    jacobolus

                    Where is the documentation for all the different charIdToTypeId names?

                    There is no comprehensive documentation for them. A lot of it you can get via the file PITerminology.h that ships with the Photoshop SDK. Various third parties have tried to gather all the IDs they could. If you google around you’ll find several such lists.

                    • 7. Re: How to manipulate layer masks in ExtendScript?
                      jacobolus Level 1

                      Do you know how to make an ActionReference for a specific layer?

                       

                      This one actually isn’t too hard:

                      var layer_ref = new ActionReference;
                      layer_ref.putIndex(app.stringIDToTypeID('layer'), 1);
                      
                      // or
                      
                      var layer_ref = new ActionReference;
                      layer_ref.putName(app.stringIDToTypeID('layer'), 'layer name');
                      
                      // or
                      
                      var layer_ref = new ActionReference;
                      layer_ref.putIdentifier(app.stringIDToTypeID('layer'), 5);
                      

                       

                      where of course you replace 1, 'layer name', 5 with the appropriate layer index, name, or ID.