What's new
Photoshop Gurus Forum

Welcome to Photoshop Gurus forum. Register a free account today to become a member! It's completely free. Once signed in, you'll enjoy an ad-free experience and be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Scripting Is there a way to pull keyword information from smart objects?


Amywhiteman

New Member
Messages
4
Likes
0
Hi,

I am trying to figure out a way to pull the file information from a smart object and append that to the file info for the parent document.

The big end goal is to come up with a process to make photoshop files searchable for both clients and in-house illustrators. Currently, our process includes (attempting) meticulously named layers and using actions and scripts to batch add layer names as keywords. The keywords are then searchable either through Finder, File Explorer or Bridge.

This works great for the most part. If we were to have all of the illustration assets as individual layers this would be an A+ solution. However, we often use smart objects and the script we are using only pulls from the current document layer names, not including layers within smart objects.

Is there an easy way to automate the process of pulling keywords from smart objects and appending them to the keywords of the parent document? If you have any thoughts let me know!

Thanks!

Here are the current scripts that we are using:

1. Add Top Level Layer Names as Keywords:
JavaScript:
// gist.githubusercontent.com/vladocar/1628924/raw/a486566b2a648f94399fffa67dc9a2b4d681b86e/layerNames.js
// Get the top level layer names for groups and layers, layers in groups are ignored
var layerNum = app.activeDocument.layers.length;
var allLayers = [];
for (var i = 0; i < layerNum; i++) {
    allLayers[i] = app.activeDocument.layers[i].name; // RegEx placeholder - name.replace(/find/gi, 'replace')
}
// Add the top level layer names to keywords
app.activeDocument.info.keywords = allLayers;

2.
JavaScript:
#target photoshop;
app.bringToFront();

if(documents.length) main();
function main(){
var Keys = getNamesPlusIDs();
if ( !ExternalObject.AdobeXMPScript ) ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
xmp = new XMPMeta( app.activeDocument.xmpMetadata.rawData );
//Uncomment the line below  to clear the keywords field
//xmp.deleteProperty(XMPConst.NS_DC,'subject');
for(var s in Keys){
xmp.appendArrayItem(XMPConst.NS_DC, "subject", Keys[s], 0,XMPConst.PROP_IS_ARRAY);
}
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
if(Keys.length > 0){
    
        }
}
function getNamesPlusIDs(){
   var ref = new ActionReference();
   ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
   var count = executeActionGet(ref).getInteger(charIDToTypeID('NmbL')) +1;
   var Names=[];
try{
    activeDocument.backgroundLayer;
var i = 0; }catch(e){ var i = 1; };
   for(i;i<count;i++){
       if(i == 0) continue;
        ref = new ActionReference();
        ref.putIndex( charIDToTypeID( 'Lyr ' ), i );
        var desc = executeActionGet(ref);
        var layerName = desc.getString(charIDToTypeID( 'Nm  ' ));
        var Id = desc.getInteger(stringIDToTypeID( 'layerID' ));
        if(layerName.match(/^<\/Layer group/) ) continue;
        var layerType = typeIDToStringID(desc.getEnumerationValue( stringIDToTypeID( 'layerSection' )));
        var isLayerSet =( layerType == 'layerSectionContent') ? false:true;
        if(!isLayerSet) Names.push(layerName);
   };
return Names.reverse();
};

Our current actions includes:
Running both scripts
Saving file
Flatten file
Save As jpg
Add text watermark
Changing file size
Save As jpg
Closing
 
Why are you running both scripts? You will end up with a lot of duplicates.
You only need to run the second script or the new script below.
The first script add all layer names to keywords but not any layers that are in layersets.
The second scripts adds all layer names to keywords.

This script adds all layer names including layers in layersets and in smartobject to keywords...
Code:
#target photoshop;
app.bringToFront();

if(documents.length) main();
function main(){
Keys =[];
Smarts =[];
getNamesPlusIDs();
for(var s in Smarts){
    selectLayerById(Smarts[s],false);
    executeAction(stringIDToTypeID("placedLayerEditContents"), undefined, DialogModes.NO );
    if(activeDocument.layers.length >1) getNamesPlusIDs();
    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
    }
if ( !ExternalObject.AdobeXMPScript ) ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
xmp = new XMPMeta( app.activeDocument.xmpMetadata.rawData );
//Uncomment the line below  to clear the keywords field
//xmp.deleteProperty(XMPConst.NS_DC,'subject');
for(var s in Keys){
xmp.appendArrayItem(XMPConst.NS_DC, "subject", Keys[s].toString(), 0,XMPConst.PROP_IS_ARRAY);
}
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
function getNamesPlusIDs(){
   var ref = new ActionReference();
   ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
   var count = executeActionGet(ref).getInteger(charIDToTypeID('NmbL')) +1;
try{
    activeDocument.backgroundLayer;
var i = 0; }catch(e){ var i = 1; };
   for(i;i<count;i++){
       if(i == 0) continue;
        ref = new ActionReference();
        ref.putIndex( charIDToTypeID( 'Lyr ' ), i );
        var desc = executeActionGet(ref);
        var layerName = desc.getString(charIDToTypeID( 'Nm  ' ));
        var Id = desc.getInteger(stringIDToTypeID( 'layerID' ));
        if(layerName.match(/^<\/Layer group/) ) continue;
        var layerType = typeIDToStringID(desc.getEnumerationValue( stringIDToTypeID( 'layerSection' )));
        var isLayerSet =( layerType == 'layerSectionContent') ? false:true;
        if(!isLayerSet) Keys.push(layerName);
        if(desc.hasKey(stringIDToTypeID( 'smartObject'))) Smarts.push(Id);
   }
}
function selectLayerById(id,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){}
    };
};
 
Hi Paul,
I am not a scripts master in any way so I was mashing two together to try and capture as many keywords as possible. I agree it is not efficient.

But this new script—AMAZING.

Thank you so much, this is extremely helpful!!
 

Back
Top