different ways to address to layers

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

tyr

different ways to address to layers

Post by tyr »

Hi gyus,

I wonder what are the ways to address specific layers in psd file between PS sessions other but by name?

Example:
I have a file with 3 layers, A, B, C.


Then I set B and C as target layers (maybe some kind of custom property or meta-data?) with script.
Then I add more layers, open/close document, move layers around but I'm able (with another script I guess) to address to those B and C layers, for example to get their name property


I can add custom data to layer via activeDocument.activeLayer.xmpMetadata.rawData property, but I'm not sure what is the good way to address to the layers with Metadata later on?

I hope this makes sense
pfaffenbichler

different ways to address to layers

Post by pfaffenbichler »

Would the ID be an option?
That is, if I remember correctly, supposed to stick as opposed to the index.

As for searching a Photoshop file for layers with any particular property I think Paul and Mike have posted useful code that utilises AM code and therefore runs faster than the DOM equivalent. (Though I would not be surprised if xbytor also had provided code to that effect …)
xbytor

different ways to address to layers

Post by xbytor »

This should work. Extracted from xtools/xlib/stdlib.js:

Code: Select allfunction cTID(s) { return app.charIDToTypeID(s); };

function getActiveLayerID() {
    var ref = new ActionReference();
    ref.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
    var ldesc = executeActionGet(ref);
    return ldesc,getInteger(cTID('LyrI'));
};
tyr

different ways to address to layers

Post by tyr »

Thanks for your replies!

ID is kinda alright: metaData would be better because I wanted to have the same 'callsign' for specific layers (grids) in different files and ID's are unique for every file.

But if I understood correctly from this topic bb/viewtopic.php?f=9&t=5575 there's no way to get metaData through AM and DOM is too slow for that.

By the way, xbytor, there's a misprint in extracted code ldesc,getInteger(cTID('LyrI')) should have '.' instead of ','
xbytor

different ways to address to layers

Post by xbytor »

tyr wrote:By the way, xbytor, there's a misprint in extracted code ldesc,getInteger(cTID('LyrI')) should have '.' instead of ','

Kinda surprised that was the only one. I just put that together on the spot. BTW, there's probably a way to get the ID without having to get the descriptor.
pfaffenbichler

different ways to address to layers

Post by pfaffenbichler »

Does this work for you?
It should create an array of array containing name, ID, metadata of layers that do have XMP metadata.
The layers could be selected by their IDs with selectLayerByID for subsequent editing or identification in DOM.
Code: Select all// 2015, use it at your own risk;
#target "photoshop-70.032"
if (app.documents.length > 0) {
app.activeDocument.suspendHistory("stuff", "main ()");
};
////////////////////////////////////
function main () {
// the file;
var myDocument = app.activeDocument;
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if not layer group or background collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
try {
   var ref = new ActionReference();
   ref.putProperty( charIDToTypeID( 'Prpr' ), stringIDToTypeID( "metadata" ) );
   ref.putIndex( charIDToTypeID( "Lyr " ), m);
   var layerDesc = executeActionGet(ref);
   var theXMP = layerDesc.getObjectValue(stringIDToTypeID( "metadata" )).getString(stringIDToTypeID( "layerXMP" ));
   theLayers.push([theName, theID, theXMP])
   }
catch (e) {
//   theLayers.push([theName, theID, /*theXMP*/])
   };
};
}
catch (e) {};
};
alert (theLayers.join("\n"));
};
// based on code by mike hale, via paul riggott;
function selectLayerByID(id,add){
add = undefined ? add = false:add
var ref = new ActionReference();
    ref.putIdentifier(charIDToTypeID("Lyr "), id);
    var desc = new ActionDescriptor();
    desc.putReference(charIDToTypeID("null"), ref );
       if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
      desc.putBoolean( charIDToTypeID( "MkVs" ), false );
   try{
    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
tyr

different ways to address to layers

Post by tyr »

pfaffenbichler, thank you so much! That'll work perfectly!
pfaffenbichler

different ways to address to layers

Post by pfaffenbichler »

Actually I don’t fully understand why I could not get the name and ID properties together with the metadata but had to insert a second executeActionGet(ref) with the "metadata" Property added individually. But the main thing is whether it works at all … 

I don’t know how you intend to proceed with the project but maybe you should keep an eye out for multiple layers with identical metadata which could happen if users duplicate layers or combine layers from multiple files.