Copy link to clipboard
Copied
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:
// 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;
and then 2. Add Layer Names as Keywords:
#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 action includes:
Running both scripts
Saving file
Flatten file
Save As jpg
Add text watermark
Changing file size
Save As jpg
Closing
Copy link to clipboard
Copied
Adapt this script to your needs.
var r = new ActionReference();
var d = new ActionDescriptor();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("json"));
r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
d.putReference(stringIDToTypeID("null"), r);
d.putBoolean(stringIDToTypeID("expandSmartObjects"), true);
eval("var json="+executeAction(stringIDToTypeID("get"), d, DialogModes.NO).getString(stringIDToTypeID("json")));
var s = "";
for (var i = 0; i < json.layers.length; i++)
s += json.layers[i].name+"\n";
s += "\n";
if (json.placed)
for (var n = 0; n < json.placed.length;n++)
{
for (var i = 0; i < json.placed[n].layers.length; i++)
s += json.placed[n].layers[i].name+"\n";
s += "\n";
}
alert(s);
Copy link to clipboard
Copied
Thanks r-bin, I appreciate your response!
Copy link to clipboard
Copied
Wow, r-bin, wow!
Copy link to clipboard
Copied
Hi again.
I posted the same question to Photoshop Gurus and got a script in response that I have found works wonderfully.
The script pulls keywords from the top-level layer, the sub-group layers, as well as layers in smart objects. The keywords auto-populate in the IPTC metadata.
#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){}
};
};
Shout out to Paul MR over at Photoshop Gurus!