Copy link to clipboard
Copied
Hi,
If possible, I'm looking for a script to update smart object layers with other image files through a batch process. I work with a file template that has a certain layout that I like in terms of where and how the layers are placed. Whenever I work on a new project, I need to replace the placed images with new images from the new project. I'm looking for a way to streamline my process by automating this. I have next to no knowledge in creating scripts. I only have basic knowledge in putting them to use, so any suggestions would be really helpful.
Typically I work with files that have between 12 and 20 smart object layers that I need to be able to replace or place a different image file within them. I'm not fussed if the image files are placed via embedding or linking. Ideally I want to be able to start the script, choose a folder from where to pull the image files and fill the 12 to 20 smart object layers individually with the 12 to 20 image files from the chosen folder.
// replace smart objects by selected files;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theSmartObjects = collectSmartObjects();
var theFiles = selectFile (true);
if (theFiles) {
for (var m = 0; m < Math.min(theSmartObjects.length, theFiles.length); m++) {
selectLayerByID(theSmartObjects[m][1], false);
replaceContents (theFiles[m])
}
};
};
////////////////////////////////////
////// collect smart objects, probably based on code by paul, mike or x //////
function collect
...
Copy link to clipboard
Copied
Template Smart Object replacements have come up many times, did you do a Forum search?
How are the replacement images for each of the Smart Objects identifyable?
Please provide sample images or at the very least meaningful screenshots (including th epertinent Panels) to clarify the naming and file-structure.
Copy link to clipboard
Copied
I've had a look through the forum
and some post were in the general field of what I'm looking for but since I don't know script they are too far off base for me to adapt to what I need. I save my files like this: myname_projectname_itemname_1. The folders are named in a similar way. The images are all 12x12 inches (3600pix by 3600 pix).
In this particular example the template has 14 smart object layers so each smart object shape layer is cropped (by width) to evenly distribute these 14 smart object shape layers across the width of the canvas (it gives the effect of paper strips).
Copy link to clipboard
Copied
Could you please provide sample files (the template and a set of replacement images)?
Copy link to clipboard
Copied
Copy link to clipboard
Copied
// replace smart objects by selected files;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theSmartObjects = collectSmartObjects();
var theFiles = selectFile (true);
if (theFiles) {
for (var m = 0; m < Math.min(theSmartObjects.length, theFiles.length); m++) {
selectLayerByID(theSmartObjects[m][1], false);
replaceContents (theFiles[m])
}
};
};
////////////////////////////////////
////// collect smart objects, probably based on code by paul, mike or x //////
function collectSmartObjects () {
// 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 collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
if(layerDesc.hasKey(stringIDToTypeID('smartObject'))) {
var soDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObject'));
var theFileRef = soDesc.getString(stringIDToTypeID('fileReference'));
var theDocID = soDesc.getString(stringIDToTypeID('documentID'));
var isLinked = soDesc.getBoolean(stringIDToTypeID('linked'));
if (isLinked == true) {
var isMissing = soDesc.getBoolean(stringIDToTypeID('linkMissing'));
var isChanged = soDesc.getBoolean(stringIDToTypeID('linkChanged'));
var thePath = soDesc.getPath(stringIDToTypeID('link'));
} else {
var isMissing = undefined;
var isChanged = undefined;
var thePath = undefined
};
/*var x = soDesc.getList(stringIDToTypeID("compsList"));
var theCompsList = soDesc.getObjectValue(stringIDToTypeID("compsList"));
if (theCompsList.count > 2) {
var theCompsList = theCompsList.getList(stringIDToTypeID("compList"));
var theSOComps = new Array;
for (var n = 0; n < theCompsList.count; n++) {
var thisOne = theCompsList.getObjectValue(n);
var compName = thisOne.getString(stringIDToTypeID("name"));
var compID = thisOne.getInteger(stringIDToTypeID("ID"));
var theComment = thisOne.getString(stringIDToTypeID("comment"));
theSOComps.push([compName, compID, theComment]);
};
theLayers.push([theName, theID, theFileRef, theDocID])
theLayers.push([theName, theID, theFileRef, theDocID, theSOComps])
};*/
theLayers.push([theName, theID, isLinked, isMissing, isChanged, thePath, theID, theFileRef, theDocID])
}
}
}
catch (e) {};
};
return theLayers
};
// 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);
}
};
////// select file //////
function selectFile (multi) {
if (multi == true) {var theString = "please select files"}
else {var theString = "please select one file"};
if ($.os.search(/windows/i) != -1) {var theFiles = File.openDialog (theString, '*.jpg;*.tif;*.psd;*.png', multi)}
else {var theFiles = File.openDialog (theString, getFiles, multi)};
////// filter files for mac //////
function getFiles (theFile) {
if (theFile.name.match(/\.(jpg|tif|psd|png)$/i) || theFile.constructor.name == "Folder") {
return true
};
};
return theFiles
};
////// replace SmartObject contents //////
function replaceContents (newFile) {
var desc3 = new ActionDescriptor();
desc3.putPath(charIDToTypeID("null"), new File(newFile));
desc3.putInteger(charIDToTypeID("PgNm"), 1);
executeAction(stringIDToTypeID("placedLayerReplaceContents"), desc3, DialogModes.NO);
};
Copy link to clipboard
Copied
Thank you so much for taking the time to do this. I can’t fully express how grateful I am through the screen but I appreciate this so much. You’ve been generous beyond belief.
Copy link to clipboard
Copied
You’re welcome!
Copy link to clipboard
Copied
Hello @c.pfaffenbichler I have tried this, but there is one problem. My image is bigger than the mockup smart object size. So it is overflowing. For your reference. I have attached the over flow version, and I have also attached the right fit size for the mockup. I humbly request, can you please kindly tell me how to modify the script, so that I get to the right fit.
Copy link to clipboard
Copied
Replacement objects/images should ideally have the same dimensions/resolution/… from the start.
There are various approaches to address the issue.
• Process the replacement images beforehand.
• Place the replacement images in the Smart Object (instead of replacing the SO’s contents) and scaling them to fit or fill.
• Get the SO’s bounds before replacement, replace, get the new bounds and transform the SO to match the previous dimensions.