Skip to main content
Inspiring
January 21, 2019
Answered

Batch replace smart objects v2

  • January 21, 2019
  • 13 replies
  • 34048 views

Greetings,

Unfortunately, my scripting knowledge is very minimal.  In using this script, the script times out and no output files occur.  I am on a pc running Photoshop CC (online subscription, latest update).  It was suggested to me by another forum member to start a new discussion thread here to assist with this problem.

This is what I have:

  •     a mockup file of a canvas wall print with the main single image set as a transformed smart object
  •     a folder of images resized to fit said smart object

This is what I would like a script to do (if possible):

  •     for every image in said folder
  •     replace smart object with images
  •     save each new mockup (one for each new image) as a JPG file.
  •     saved name should be the original image file name (saved in a different directory).  if this naming convention is not possible, its ok as i can rename the files later.

We have over 50k of mockups to do for this particular canvas shape/size....

Any suggestions on how I could streamline this process without having to manually replace and save?  THANK YOU!!!

// replace smart object’s content and save psd;

// 2011, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

var myDocument = app.activeDocument;

var theName= myDocument.name.match(/(.*)\.[^\.]+$/)[1];

var thePath = myDocument.path;

var theLayer = myDocument.activeLayer;

// psd options;

psdOpts = new PhotoshopSaveOptions();

psdOpts.embedColorProfile = true;

psdOpts.alphaChannels = true;

psdOpts.layers = true;

psdOpts.spotColors = true;

// check if layer is smart object;

if (theLayer.kind != "LayerKind.SMARTOBJECT") {alert ("selected layer is not a smart object")}

else {

// select files;

if ($.os.search(/windows/i) != -1) {var theFiles = File.openDialog ("please select files", "*.psd;*.tif;*.jpg", true)}

else {var theFiles = File.openDialog ("please select files", getFiles, true)};

if (theFiles) {

// work through the array;

          for (var m = 0; m < theFiles.length; m++) {

// replace smart object;

                    theLayer = replaceContents (theFiles, theLayer);

                    var theNewName = theFiles.name.match(/(.*)\.[^\.]+$/)[1];

//Raise color picker for Back cover;

try {

app.activeDocument.activeLayer = app.activeDocument.layers[app.activeDocument.layers.length - 1];

// =======================================================

var idsetd = charIDToTypeID( "setd" );

var desc7 = new ActionDescriptor();

var idnull = charIDToTypeID( "null" );

var ref2 = new ActionReference();

var idcontentLayer = stringIDToTypeID( "contentLayer" );

var idOrdn = charIDToTypeID( "Ordn" );

var idTrgt = charIDToTypeID( "Trgt" );

ref2.putEnumerated( idcontentLayer, idOrdn, idTrgt );

desc7.putReference( idnull, ref2 );

var idT = charIDToTypeID( "T   " );

var desc8 = new ActionDescriptor();

var idClr = charIDToTypeID( "Clr " );

var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );

desc7.putObject( idT, idsolidColorLayer, desc8 );

executeAction( idsetd, desc7, DialogModes.ALL );

} catch (e) {};

//save jpg;

                    myDocument.saveAs((new File(thePath+"/"+theName+"_"+theNewName+".psd")),psdOpts,true);

                    }

          }

}

};

////// get psds, tifs and jpgs from files //////

function getFiles (theFile) {

     if (theFile.name.match(/\.(psd|tif|jpg)$/i) != null || theFile.constructor.name == "Folder") {

          return true

          };

     };

////// replace contents //////

function replaceContents (newFile, theSO) {

app.activeDocument.activeLayer = theSO;

// =======================================================

var idplacedLayerReplaceContents = stringIDToTypeID( "placedLayerReplaceContents" );

    var desc3 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

    desc3.putPath( idnull, new File( newFile ) );

    var idPgNm = charIDToTypeID( "PgNm" );

    desc3.putInteger( idPgNm, 1 );

executeAction( idplacedLayerReplaceContents, desc3, DialogModes.NO );

return app.activeDocument.activeLayer

};
This topic has been closed for replies.
Correct answer mpspringer

thank you JJMack​ !!

this script is working great now!  Here is the final working script:

// replace smart object’s content and save psd;

// 2011, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

    var myDocument = app.activeDocument;

    var theName = myDocument.name.match(/(.*)\.[^\.]+$/)[1];

    var thePath = myDocument.path;

    var theLayer = myDocument.activeLayer;

    // psd options;

    psdOpts = new PhotoshopSaveOptions();

    psdOpts.embedColorProfile = true;

    psdOpts.alphaChannels = true;

    psdOpts.layers = true;

    psdOpts.spotColors = true;

    // check if layer is smart object;

    if (theLayer.kind != "LayerKind.SMARTOBJECT") {

        alert("selected layer is not a smart object")

    } else {

        // select files;

        if ($.os.search(/windows/i) != -1) {

            var theFiles = File.openDialog("please select files", "*.psd;*.tif;*.jpg", true)

        } else {

            var theFiles = File.openDialog("please select files", getFiles, true)

        };

        if (theFiles) {

            // work through the array;

            for (var m = 0; m < theFiles.length; m++) {

                // replace smart object;

                theLayer = replaceContents(theFiles, theLayer);

                var theNewName = theFiles.name.match(/(.*)\.[^\.]+$/)[1];

                //save jpg;

                var jpegOptions = new JPEGSaveOptions();

                jpegOptions.quality = 10;

                jpegOptions.embedColorProfile = true;

                jpegOptions.matte = MatteType.NONE;

                myDocument.saveAs((new File(thePath + "/" + theNewName + ".jpg")), jpegOptions, true);

            }

        }

    }

};

////// get psds, tifs and jpgs from files //////

function getFiles(theFile) {

    if (theFile.name.match(/\.(psd|tif|jpg)$/i) != null || theFile.constructor.name == "Folder") {

        return true

    };

};

////// replace contents //////

function replaceContents(newFile, theSO) {

    app.activeDocument.activeLayer = theSO;

    // =======================================================

    var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");

    var desc3 = new ActionDescriptor();

    var idnull = charIDToTypeID("null");

    desc3.putPath(idnull, new File(newFile));

    var idPgNm = charIDToTypeID("PgNm");

    desc3.putInteger(idPgNm, 1);

    executeAction(idplacedLayerReplaceContents, desc3, DialogModes.NO);

    return app.activeDocument.activeLayer

};

13 replies

Known Participant
October 20, 2023

I would point out a few important things about automating this process:

I've used a similar script to automate mockup creation, and I had a few major problems I encountered while running it. One of the biggest problems was, while the script would run to create the mockups? The RAM usage on my computer by Photoshop would steadily increase -- to the point that everything would run slower, and slower, sometimes causing Photoshop to completely crash midway through the operation.

 

I found that several key improvements were necessary for preventing this from happening: First, add a section to your script where, after each replace-and-save/export operation inside of your loop, it purges all caches. Second, make sure to set your "History States" in the Photoshop Preferences to as low as possible, while this runs. I found these to be MAJOR contributors to this process slowing my computer / increasing RAM usage, as it would run.

 

While I wish there was a way to programmatically change your History States to 0 or 1 at the start of the .jsx script, then change it back to 25 or 50 or whatever your setting was the end of it -- as far as I could tell from my research, there is no way to programmatically change your History States like that via .jsx scripting. This means you need to remember to do it manually before you run the script, then remember to change it back after you're finished. Otherwise, it'll be stuck in that high state + your RAM usage might grind your computer to a halt, OR it'll be stuck in that low state and when you're working on something in Photoshop later and need to Ctrl + Z to undo something, the operation will fail because your History States is set too low. I found this to be a major pain in the ass, actually, because I would constantly forget to revert it back. Maybe you could programatically remind yourself, with a pop-up alert, message, before/after the script executes or something.

 

 

Then in terms of optimization, I found several key ways to dramatically increase the execution speed of these automated mockup-creation scripts -- which, in turn, would allow me to do way more throughput/volume, per unit time, of mockup creation. One obvious, easy win is to simply reduce the size of the .psd document you're using for the batch Smart Object replacement operations. Mockup templates often come in gigantically massive files that are just way bigger than are practically needed for basic product images or graphic design workflows. I reduced by Photoshop document to be resized to the final dimensions of the actual JPEG images I was exporting -- so by taking it down from the initial massive 4000 x 4000 size, down to 1000 x 1000, that by itself made a DRAMATIC improvement to the execution speed.

 

Additionally, I found that simply minimizing all panels while the script executed actually made it run about 20% faster. It may not seem like much, but if you're doing tons of volume, 20% can translate into HOURS saved. (Note that this is one that you CAN trigger programmatically, in your .jsx script. So my script would automatically hide the panels at the start, to make it run faster, then revert it back when it was finished. Gave it a nice little performance boost.)

 

Another major performance boost came from compacting my code + condensing steps, where possible. For example, I had post-processing batch operations that would compress all the final v1 images to create the final v2 images. I was able to just add a few extra lines to the script to save those exported JPEGs as the desired final compression level to begin with, which functionally shaved like another 20% off the execution time -- since it eliminated the need to do any secondary compression at all.

 

You can also set these scripts to be executable via keyboard shortcuts in Photoshop if you like. Or you can just select them via the File > Scripts section. Either way.

 

 

A few other points on this: If you're not very technically inclined, don't know how to write computer programs, or otherwise don't want to bother figuring out how to automate this process using .jsx scripting, there is a simple Photoshop plugin that automates this process for you called "Batch-Replace Smart Objects". It's basically a plugin that allows you to batch-generate mockup images, using Photoshop mockup templates like those you'd get from the Etsy Marketplace or Creative Market. So instead of having to tinker with scripts, customize them for your needs, figure out how to use Photoshop's notoriously inscrutable ActionReference commands, you can use that plugin to quickly automate these batch mockup creation operations. Here's what the panel looks like inside of my Photoshop workspace:

 

 

Note that I've used this plugin for very large batch sizes (1000+ mockups being created at once), and I didn't encounter the "RAM usage increasing" issue that I faced with the scripting approach. It also doesn't require me to change my History States for it to avoid that "RAM creep" problem. I believe that's just because the nature of how the operations run, via the .jsx scripting approach, compared against the UXP development approach that you see with Photoshop plugins (.jsx scripting vs. UXP = basically just different ways of executing commands programmatically in Photoshop.) 

 

I've also used it for multi-step mockup creation workflows -- for example, if you need to create several different mockup images for all new products being added to your store. You can just create + save multiple step operations, then run them as needed in the Workflows section. Last things I'd point out is, the ability to specify the JPEG save quality can save you the additional post-processing step of batch-compressing all your images, to be the desired file size. Then the "stretch images to fit Smart Object" option can save you the pre-processing step of needing to batch-resize all your images to perfectly fit your Smart Object's aspect ratio. It's basically a simple plugin that effectively does what a lot of these scripts try to do. Just two different ways of achieving the same goal.

Known Participant
October 14, 2023

Note that if you're struggling with the ActionReference side of things (when trying to customize your .jsx script), there are some ScriptingListener tools you can use -- where you basically perform those operations manually, and it will log the Action Reference commands that would execute those operations -- and you can use this to find out what code is needed to do certain things. I've used it a few times when struggling how to figure out what code I needed to use for certain things where I couldn't find any resources online.

New Participant
September 29, 2022

Hi all,

 

I was hoping someone could help me. This script is perfect for what I want to do apart from the input and export! Is there a way I can change the script to be able to load PDF files and then export as PNG files? Rather than PSD and jpegs?

Thanks in advance!

piXelsplasher
Inspiring
October 5, 2022

Realizing that users of Pixelsplasher Batch Smart Layer Replace have broad needs, I will be adding PDF and maybe all other built-in file input formats of Photoshop for smart layers.

 

Here is the list of files to be made available to Photoshop as inputs.

 

I will post an announcement here soon when this feature is ready so you could be one of its users.

New Participant
November 15, 2022

@piXelsplasher I have been using jpegs in the meantime in stead of PDFs. I have paid for and downloaded your script and I cannot get it to install properly. Could you send me a zip file like I have seene you have sent others?

New Participant
May 27, 2022

How does this script works ??? what is my input ? i get 2 pop ups to "select" and to "place" ,, what does that mean ?

New Participant
April 25, 2020

Could you please check this mockup?

https://drive.google.com/file/d/13eMjgWSvlidhpyopm2n56IHyPWirpRDB/view?usp=sharing

it gives me error "selected object is not a smart object"

JJMack
Adobe Expert
April 25, 2020

How do you intend to user that As a template.  Most Template have a Smart Object layer that has a design to be replaced. Or a  Layer that is changed that is clipped or masked by and overlay. The template you posted has a 3D object that need its surface material replaced. You would to develop a method to do that and be careful not to touch the 3d object position are all because the are overlays in the document.  I have not see any automated Script or actions to do something like that and  I do not know how one would.   For myself I have made a template for a couple of 3D objects surface materials a Photo Collage template. That I populate and tham edited into 3D layers that has a Video timeline to animated the object. There are no overlays in the document layers. Overlays would need to be within the 3D scene and be animated as well not be is some other dimension in the documents layers.

JJMack
New Participant
April 25, 2020

If you need to auto-replace, auto-transform and auto-export to JPG or PNG the smart layers that are on a 3D Layer object, the 3D Layer Add-on for Batch Smart Layer Replace script can help you. It is not free, however, but can save you a lot of time.

 

Here is a video demo of it:


Amazing! Thank you. 

nguyenhuybao
New Participant
February 12, 2020

hello, I have tried to use your script with a bit of modification, It's just about the import files' format, I change them to .png. But it didn't work at all, it always says "Error 21: undefined is not an object", there is an issues with line 55 "var theNewName = theFiles.name.match(/(.*)\.[^\.]+$/)[1]". Any help please?

 

There is the script I used:

#target photoshop

if (app.documents.length > 0) {

var myDocument = app.activeDocument;

var theName = myDocument.name.match(/(.*)\.[^\.]+$/)[1];

var thePath = myDocument.path;

var theLayer = myDocument.activeLayer;

// psd options;

psdOpts = new PhotoshopSaveOptions();

psdOpts.embedColorProfile = true;

psdOpts.alphaChannels = true;

psdOpts.layers = true;

psdOpts.spotColors = true;

// check if layer is smart object;

if (theLayer.kind != "LayerKind.SMARTOBJECT") {

alert("selected layer is not a smart object")

} else {

// select files;

if ($.os.search(/windows/i) != -1) {

var theFiles = File.openDialog("please select files", "*.png", true)

} else {

var theFiles = File.openDialog("please select files", getFiles, true)

};

if (theFiles) {

// work through the array;

for (var m = 0; m < theFiles.length; m++) {

// replace smart object;

theLayer = replaceContents(theFiles, theLayer);

var theNewName = theFiles.name.match(/(.*)\.[^\.]+$/)[1];

//save jpg;

var jpegOptions = new JPEGSaveOptions();

jpegOptions.quality = 10;

jpegOptions.embedColorProfile = true;

jpegOptions.matte = MatteType.NONE;

myDocument.saveAs((new File(thePath + "/" + theNewName + ".jpg")), jpegOptions, true);

}

}

}

};

////// get psds, tifs and jpgs from files //////

function getFiles(theFile) {

if (theFile.name.match(/\.(png)$/i) != null || theFile.constructor.name == "Folder") {

return true

};

};

////// replace contents //////

function replaceContents(newFile, theSO) {

app.activeDocument.activeLayer = theSO;

// =======================================================

var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");

var desc3 = new ActionDescriptor();

var idnull = charIDToTypeID("null");

desc3.putPath(idnull, new File(newFile));

var idPgNm = charIDToTypeID("PgNm");

desc3.putInteger(idPgNm, 1);

executeAction(idplacedLayerReplaceContents, desc3, DialogModes.NO);

return app.activeDocument.activeLayer

};

JJMack
Adobe Expert
February 12, 2020

I would suggest the you find a better script.  To me it look like the code in the script is bad.   The for loop looks like its is processing a file list.   Which you created by selecting some number of files in a file open dialog that allows more then one file to be selected..  The File List is stored in an Array named "theFiles". The loop is control using the var m which is initialized to 0 for the first array element,  and is incremented  with "m++" at the end of an interaction of the loop. When "m" becomes equal to the number of the array elements "theFiles.length" the loop ends.   In  for loop you should see that an array element is being processed "theFiles[m]".   That code is not in there.  The first png file may be repeatedly replaced the mockup objecy  the the jpeg file repeatedly saved over. Or the line "var theNewName = theFiles.name.match(/(.*)\.[^\.]+$/)[1];" may simly fail because "theFiles" is not a file object. 

 

The script also uses Photoshop smart object layer feature Replace Content.  Which mean all replacement object need to be the Sand Aspect Ratio, Size and Print resolution of the object in the mockup template.   The mat bet as Problem with the Object in the mockuo template if you Placed in a PNG creating the template.  Place may have trimmed transparent boarders if the png file had any.  When  ever I create Png files that I may place onto document I will insure the top left and bottom right document pixels and not empty  that they have at least a 1% opacity gray pixel the png will not have ant transparent borders.

 

You may want to look at the Batch Mockup Scripts I have added to  package Free Photoshop Photo Collage and Mockup Toolkit  The scripts use replace content by default but have an edit option thar edit the objects rather the use replace content. Replacemebt images can be any size.

JJMack
piXelsplasher
Inspiring
November 12, 2019

There is now an extension at Adobe Exchange for batch replacement of one or more smart layers with comp layer support:

Pixelsplasher Batch Smart Layer Replace 

This extension can replace multiple smart layers at every export and can auto-fit the replaced image to the original dimension of the replaced smart layer so there is no need to resize the source images.

FEATUREShttps://www.pixelsplasher.com/_downloads/scripts/batch-replace-smart-layer-content-script-for-adobe-photoshop/

Participating Frequently
November 12, 2019

Yeah. I've seen this extension so many months ago. But I can't afford it. 

JJMack
Adobe Expert
January 24, 2019

I downloaded your script an created a single layered  smart object document and did 70 not problem nos selecter 217 seem to be working

yes 217 no problem

Old Dell workstation

Dual 6 core xeon slow 2ghz

40GB ECC Ram

256GB SSD

JJMack
Inspiring
January 24, 2019

added some alerts to the script (see below)

in running it, i did see the issue occur at ~750 image files.   it did work at 725 image files.

is there a limit setting somewhere?   this is very odd

// replace smart object’s content and save psd;

// 2011, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

    var myDocument = app.activeDocument;

    try {

        var theName = myDocument.name.match(/(.*)\.[^\.]+$/)[1];

    } catch (e) {

        alert(e);

    }

    var thePath = myDocument.path;

    var theLayer = myDocument.activeLayer;

    // psd options; 

    psdOpts = new PhotoshopSaveOptions();

    psdOpts.embedColorProfile = true;

    psdOpts.alphaChannels = true;

    psdOpts.layers = true;

    psdOpts.spotColors = true;

    // check if layer is smart object; 

    if (theLayer.kind != "LayerKind.SMARTOBJECT") {

        alert("selected layer is not a smart object")

    } else {

        // select files; 

        if ($.os.search(/windows/i) != -1) {

            var theFiles = File.openDialog("please select files", "*.psd;*.tif;*.jpg", true)

        } else {

            var theFiles = File.openDialog("please select files", getFiles, true)

        };

        alert("theFiles.length=" + theFiles.length);

        if (theFiles) {

            // work through the array; 

            for (var m = 0; m < theFiles.length; m++) {

                // replace smart object; 

                alert("try to process file:\n" + theFiles);

                theLayer = replaceContents(theFiles, theLayer);

                var theNewName = theFiles.name.match(/(.*)\.[^\.]+$/)[1];

                //save jpg; 

                var jpegOptions = new JPEGSaveOptions();

                jpegOptions.quality = 10;

                jpegOptions.embedColorProfile = true;

                jpegOptions.matte = MatteType.NONE;

                myDocument.saveAs((new File(thePath + "/" + theNewName + ".jpg")), jpegOptions, true);

            }

        }

    }

};

alert("Done!");

////// get psds, tifs and jpgs from files ////// 

function getFiles(theFile) {

    try {

        if (theFile.name.match(/\.(psd|tif|jpg)$/i) != null || theFile.constructor.name == "Folder") {

            return true

        };

    } catch (e) {

        alert(e);

    }

};

////// replace contents ////// 

function replaceContents(newFile, theSO) {

    try {

        app.activeDocument.activeLayer = theSO;

        // ======================================================= 

        var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");

        var desc3 = new ActionDescriptor();

        var idnull = charIDToTypeID("null");

        desc3.putPath(idnull, new File(newFile));

        var idPgNm = charIDToTypeID("PgNm");

        desc3.putInteger(idPgNm, 1);

        executeAction(idplacedLayerReplaceContents, desc3, DialogModes.NO);

        return app.activeDocument.activeLayer

    } catch (e) {

        alert(e);

    }

};

JJMack
Adobe Expert
January 25, 2019

mpspringer  wrote

added some alerts to the script (see below)

in running it, i did see the issue occur at ~750 image files.

What was "THE ISSUE" 

How big are your image.  I did notice the RAM usage keep climbing. I do not understand Why There is only one document that has one Smart Object replaced many times.   I just ran a 876 batch RAM usage climb from 4GB to 19GB slowly but steadily.  I did comment out the save to the output files were never written. However the object was replace 876 time and too my slow machine over ten minutes 

JJMack
Inspiring
January 24, 2019

PC

high end dell laptop

i7, 32BG ram, 1TB hd

JJMack
Adobe Expert
January 24, 2019

Are you using a PC or  a Mac?

JJMack