Skip navigation
lee zjnu
Currently Being Moderated

How to get the style of a  layer using photoshop scripting ??

Sep 3, 2010 6:54 PM

As I know  there is a method  ApplyStyle(string)  which is uesd to apply the specified style to a layer. But I really don't know how to get the style name of a layer ?

Anyone who knows? Please help me!   Thank you !

  • Currently Being Moderated
    Community Member
    Sep 4, 2010 4:21 AM

    I’m afraid there’s no way to get the name of a Style from a Layer as Styles don’t work that way – but maybe someone else knows different …

     

    I suppose a work-around would be to copy the style and paste it on the intended layer; you should be able to use Scripting Listener-code for that, something like this:

     

    function transferEffects (layer1, layer2) {

    app.activeDocument.activeLayer = layer1;

    var id157 = charIDToTypeID( "CpFX" );

    executeAction( id157, undefined, DialogModes.ALL );

    app.activeDocument.activeLayer = layer2;

    var id158 = charIDToTypeID( "PaFX" );

    executeAction( id158, undefined, DialogModes.ALL );

    };

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 4, 2010 7:05 AM

    There is a key layerFXVisible that I think will tell you if a style is applied but im still not any good with how to get these… One of the others will no doubt show us both…

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 4, 2010 9:33 AM

    There are limits as to what can be code using Photoshops Scripting interface. Adobe does not supply methods for everything that can be done in Photoshop. Photoshop also ships with a plug-in named ScriptListener. Liken it to the Actions Palette Action Recorder without controls. When installed anything that can be recorded by Photoshop will be written to two files one in VSB script format and one in javascript format.  Like actions these are step step step no logic and all hard coded variables. Photoshop can not record everything and the code generated by the ScriptListener is for the Action Manager and looks a lot like that above function.  Though the ScriptListener code is step step you can take the code generated for a step and turn it into a function by add the function name ( parm, parm) { and replacing some of the hard coded variable with the parm variables }  The code is not all that readable.

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 4, 2010 9:56 AM

    Part of the code Mark posted is scriptlistener( action manager ) code. It can be hard to understand but it is the only way to work with layer styles in scripting.

     

    Below are two functions. One checks for layer effects( styles ). It will return true if the layer has any effect applied. The other just checks for the stroke fx. It will only return true if the layer has a stroke effect. You can make similar functions to test for other effects, if the effects are visible, etc.

     

    Getting the settings used in an effect is somewhat harder but is done with action manager as well. You get the descriptor for the layer. From that you get the descriptor for the layer effects. Then you get the descriptor for the effect itself from that descriptor.

     

    Because each of the 10 effects has different descriptors(settings) and those descriptors are not documented by Adobe it takes some work to build each function. The last function below shows one way to get the size of the stoke effect. The size is in pixels.

     

    function hasLayerFX(){
         var ref = new ActionReference();
         ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
         return  executeActionGet(ref).hasKey(stringIDToTypeID('layerEffects'));
    };
    
    function hasStrokeFX(){
         var res = false;
         var ref = new ActionReference();
         ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
         var hasFX =  executeActionGet(ref).hasKey(stringIDToTypeID('layerEffects'));
         if ( hasFX ){
              var ref = new ActionReference();
              ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
              res = executeActionGet(ref).getObjectValue(stringIDToTypeID('layerEffects')).hasKey(stringIDToTypeID('frameFX'));
         }
         return res;
    };
    
    function getStrokeSize(){
        try{
            var ref = new ActionReference();
            ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
            var desc = executeActionGet(ref).getObjectValue(stringIDToTypeID('layerEffects')).getObjectValue(stringIDToTypeID('frameFX'));
            return desc.getUnitDoubleValue(stringIDToTypeID('size'));
        }catch(e){}
    };
    
    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 5, 2010 2:29 AM

    The following code would copy the effects applied to a Layer named »styleLayer« and paste them to the currently selected Layer if »styleLayer« is a top level Layers. 

    Naturally there is no need to identify the fx-layer by name, one could also create some dialog or identify it by some other mean.

     

    if (app.documents.length > 0 && app.activeDocument.layers.length > 1) {

    transferEffects(app.activeDocument.layers.getByName("styleLayer"), app.activeDocument.activeLayer);

    };

    ////// function to copy layer effects of one layer and apply them to another one //////

    function transferEffects (layer1, layer2) {

    app.activeDocument.activeLayer = layer1;

    try {

    var id157 = charIDToTypeID( "CpFX" );

    executeAction( id157, undefined, DialogModes.ALL );

    app.activeDocument.activeLayer = layer2;

    var id158 = charIDToTypeID( "PaFX" );

    executeAction( id158, undefined, DialogModes.ALL );

    } catch (e) {

    alert ("the layer has no effects");

    app.activeDocument.activeLayer = layer2;

    }

    };

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 5, 2010 3:13 AM

    This is only a thought but if you started off with some layers with styles applied. Is it possible to not only copy the FX over but have the name of the used style in layer metadata? and bring that too? With a second function… just thinking aloud can't try any of this… don't have metadata in my layers so Im unsure what you can do with it yet…

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 5, 2010 7:10 AM

    Muppet Mark wrote:

     

    This is only a thought but if you started off with some layers with styles applied. Is it possible to not only copy the FX over but have the name of the used style in layer metadata?

    If the style name is in the metadata, yes you could. For that matter you wouldn't need to copy the effects. You could just get the name and apply that style to the target layer.

     

    But unlike document metadata, Photoshop does not create layer metadata automatically. So unless the user creates the metadata and add the style name when they apply the style or there is an event handler running for the ApplyStyle event that does the same there is still no good way to know the name of the style by just looking at the layer effects.

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 5, 2010 7:31 AM

    Mike, does a document's metadata inherit layer metadata? If you added a namespace etc. and put some data in it would this be visible to apps or the OS outside of Photoshop or is this just something that Photoshop stores in the file for its own usage?

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 5, 2010 10:17 AM

    Layer metadata was added in CS4. Photoshop does not store any data there for it's own use. In fact a layer will only have metadata if a user has added it through a script or custom panel.

     

    There are no ties between document and layer metadata and as far as I know the only way to read layer metadata is in an open document via a script or custom panel. The Photoshop GUI doesn't display, allow access, or even show a layer has metadata( layer metadata is not created when a layer is created ).

     

    As far as I know other apps such as Bridge can access/display layer metadata.

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 6, 2010 10:40 AM

    That function only checks the active layer. If the active (target) layer has an effect it should return true.

     

    Here are the stringIDs for the 10 layer effects.

     

    'dropShadow'
    'innerShadow'
    'outerGlow'
    'innerGlow'
    'bevelEmboss'
    'solidFill' // color overlay
    'gradientFill' // gradient overlay
    'patternFill' // pattern overlay
    'chromeFX' // satin
    'frameFX' // stroke

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 7, 2010 8:09 AM

    Try this...

    ps.ApplicationClass app = new ps.ApplicationClass();
    String Code = "var ref = new ActionReference();" +
    "ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') ); " +
    "  ReturnCode =  executeActionGet(ref).hasKey(stringIDToTypeID('layerEffects'))?'Style Exists' :'Style Does Not Exist';";
    String ReturnCode = app.DoJavaScript(Code, null, null);
    MessageBox.Show(ReturnCode);
    
    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 7, 2010 8:39 PM

    I'm sorry I should have asked which version of Photoshop you are using. The 'layerEffects' key was not added to the layer descriptor until CS3. I don't know of a way to access info about a layer's effects via scripting in versions before CS3.

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 8, 2010 4:45 AM

    Mike, your function NO work for me either (because of the version thing) I did post earlier that I could see…

     

    Key 9 = layerFXVisible : DescValueType.BOOLEANTYPE

     

    In the output from a script that you gave me… I still struggle like hell with these but would this NOT at least indicate the state of an effect on a layer? I can see this in my CS2… I can see its type so I tried using getBoolean() but it NO work…

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 8, 2010 8:26 AM

    You should be able to get the value of that key in CS2.

     

    var ref = new ActionReference();
    ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
    var bool = executeActionGet(ref).getBoolean(stringIDToTypeID('layerFXVisible'));
    alert(bool);
    

     

    But it is not that useful. It is really a document property. Under normal conditions it will be set to true even if the layer does not have an effect or the effect has been turned off using the panels visibility icon. To have it set to false you have to right click on an effect and choose 'Hide All Effects' from the pop-up menu. That hides the effects document wide, not just the target layer. Scriptlistener records that menu item as setting a document property even though it is not in the document's descriptor.

     

    var desc = new ActionDescriptor();
         var ref = new ActionReference();
         ref.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( "lfxv" ) );
         ref.putEnumerated( charIDToTypeID( "Dcmn" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
    desc.putReference( charIDToTypeID( "null" ), ref );
         var desc2 = new ActionDescriptor();
         desc2.putBoolean( charIDToTypeID( "lfxv" ), false );
    desc.putObject( charIDToTypeID( "T   " ), charIDToTypeID( "lfxv" ), desc2 );
    executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
    
    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 8, 2010 9:11 AM

    Mike, thanks it looks like a case of mistaken ID and you are right it does not deliver what I was expecting it to… No surprise there… One function returned false all the time now that one's true… I also tried to copy FX from a layer to see if it had any but I couldn't catch that properly either…

    |
    Mark as:
  • Currently Being Moderated
    Sep 12, 2010 11:25 AM

    Does anybody know how we can take the properties of a layer style? For example, the colors of the gradient fill, etc.

    Thanks in advance!

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 12, 2010 11:49 AM

    jconor29 wrote:

     

    Does anybody know how we can take the properties of a layer style? For example, the colors of the gradient fill, etc.

     

    What version of Photoshop are you using? I can show you how to get info about a layer's effects but it requires CS3 or higher.

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 13, 2010 12:17 AM
    I am  eager   to  know  it  either,  but  no  answer

    Michael L Hale just offered to explain how to do it, didn’t he?

    But he wants to know the Photoshop versions in use.

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 13, 2010 3:13 AM

    Hello, I just saw your answer. Thank you. I am using Photoshop CS4.

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 13, 2010 7:50 AM

    This may need more testing and you might want to change it if you are only interested in the colors used in the gradient but it should give you a good start. Note it requires CS3 or higher.

     

    function getGradientInfo(){
        try{
            var ref = new ActionReference();
            ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
              // get gradient descriptor
            var desc = executeActionGet(ref).getObjectValue(stringIDToTypeID('layerEffects')).getObjectValue(stringIDToTypeID('gradientFill')).getObjectValue(stringIDToTypeID('gradient'));
              // get an ActionList of color settings used in gradient
              var colorsList = desc.getList(stringIDToTypeID('colors'));
              var count = colorsList.count;// the number of color stops in gradient
              var colors = [];// array to hold custom color objects
              for( var c = 0; c < count; c++ ){
                   desc = colorsList.getObjectValue(c);// get color descriptor
                   var colorStop = {};// object to hold color stop info
                   colorStop.location = desc.getInteger(stringIDToTypeID('location'));
                   colorStop.midpoint = desc.getInteger(stringIDToTypeID('midpoint'));
                   colorStop.type = typeIDToStringID(desc.getEnumerationValue(stringIDToTypeID('type')));
                   
                   var colorDesc = desc.getObjectValue(stringIDToTypeID('color'));
                   var color = new SolidColor();
                   switch(app.activeDocument.mode){
                        case DocumentMode.GRAYSCALE:
                             color.gray.gray = colorDesc.getDouble(charIDToTypeID('Gry '));
                             break;
                        case DocumentMode.RGB:
                             color.rgb.red = colorDesc.getDouble(charIDToTypeID('Rd  '));
                             color.rgb.green = colorDesc.getDouble(charIDToTypeID('Grn '));
                             color.rgb.blue = colorDesc.getDouble(charIDToTypeID('Bl  '));
                             break;
                        case DocumentMode.CMYK:
                             color.cmyk.cyan = colorDesc.getDouble(charIDToTypeID('Cyn '));
                             color.cmyk.magenta = colorDesc.getDouble(charIDToTypeID('Mgnt'));
                             color.cmyk.yellow = colorDesc.getDouble(charIDToTypeID('Ylw '));
                             color.cmyk.black = colorDesc.getDouble(charIDToTypeID('Blck'));
                             break;
                        case DocumentMode.LAB:
                             color.lab.l = colorDesc.getDouble(charIDToTypeID('Lmnc'));
                             color.lab.a = colorDesc.getDouble(charIDToTypeID('A   '));
                             color.lab.b = colorDesc.getDouble(charIDToTypeID('B   '));
                             break;
                   }
                   colorStop.color = color;
                   colors.push(colorStop);
              }
              return colors;
        }catch(e){}
    };
    var colorstops = getGradientInfo();
    alert('first color stop color(rgb):\r'+colorstops[0].color.rgb.red+','+colorstops[0].color.rgb.green+','+colorstops[0].color.rgb.blue);
    
    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 14, 2010 12:38 AM

    Thank you! It was very useful.

    |
    Mark as:
  • Currently Being Moderated
    Community Member
    Sep 22, 2010 1:59 AM

    Can we see if a layer effect is hidden or shown?

    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points