Skip to main content
Inspiring
January 21, 2019
Answered

Batch replace smart objects v2

  • January 21, 2019
  • 13 replies
  • 34325 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

Inspiring
January 24, 2019

Found an issue and do not know the solution.

Issue: when selecting more than ~50 image files, the script seems to time out and nothing occurs at all.  very strange.

what could be causing this behavior?

mpspringerAuthorCorrect answer
Inspiring
January 22, 2019

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

};

JJMack
Community Expert
Community Expert
January 22, 2019

I like that you fixed up the script for yourself you ask for help and made the modification need with the little help provided. Good show thank you...

you may want to change

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

JJMack
SilverRowan
Participant
August 17, 2020

Hi JJMack,

I wanted to say thank you for your set of scripts, they're amazing

Just to let you know, in the 2020 version of photoshop they throw an error at first, if I comment out line 28 (//@include "PCTpreferences.jsx") they run, but I have NO idea what I just turned off.

As well, the buttons in the dialog box don't actually allow me to browse - is this what I commented out? any idea how to get those to work properly?

The script works, but I have to copy and paste in the file locations and names.
Hopefully this helps anyone else who's getting an error with them.

JJMack
Community Expert
Community Expert
January 22, 2019

How are you running that script.  The script is designed to be run with an  open layered document that you target that is a smart object layer you that want to replace its content.  Once you target that smart object layer you run the script.  The script should open an Open Files dialog for you to select the image files you want to use as replacement images.  The image file types can be PSD, Tif and Jpeg.  The script will then replace the smart object layer object's with the images  and save PSD files not jpeg files in the same folder as the open document you run the script on.  It also try to do  something about a  back cover so the open document must have some other layer that is a back cover.

If you have 50K mockup you would need to open them one at a time target a smart object layer run the script,  select the replacement images files.  You  have a lot of work to do.  You could easily change the script to so all you would need to do is select the folder containing your replacement images and save Jpeg files not PSD file. Still you  would need to open 50K image files one at a time target the smart object layer and select a folder of image files.  

When you want to Process 50,000 mockup files you do not want to need that much human interaction you would want to automate the process of targeting the smart object layer and selecting the folders that contain the proper set of replacement images for each mockup. You would want to batch process your mockup not have to run 50,000 mockup jobs to populate your mockups.   You need to design a mockup template design that can be batch populated.  The develop the batch populating process and script it.

JJMack
Inspiring
January 22, 2019

Thank you for your detailed response.  Please let me clarify what this project entails.

1 PSD Mockup file (layered, with a Smart Object layer)

50k replacement image files

I removed the section of code that contained "the back cover" layer as it was not needed.  After some trial and errors, the script began to work well.

How can the script be modified so it saves the final output as a jpg (not psd)?

// 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;

                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

};

Participating Frequently
May 24, 2020

If you think about it. The first script of mine you used to replace one smart object is very simple and easy. It is also the basics for the other two scripts.

 

For the single smart object you pointed the script to a template, to a sequences of replacement images. And a folder to store the populated jpeg images. The script would open the template and replace the content of the object with an replacement and saved a jpeg,  repeat the replace step and save step till all replacements were done then terminate.

 

The complexity come in the the replace step.  If the script uses replace content all the replacement image need to be the same size, aspect ratio and have the same print resolution.  However, there is an alternative way to replace and object's contents that is the Object can be edited and its content altered.  This add extra complexity for all possible object would not be edited by Photoshop.   If a template's smart object is a placed RAW file or a AI vector file like .svg or .ai.  The object would be edited by ACR or AI not Photoshop.  So the replace step, if edit option is used can not handle smart object layers that object would not be edited by Photoshop. These layers will not be replace you will be informed of this and you should re-work the template if you want to use the edit option to be able to use any size image.

 

So the simple replace object became a complex step.  Still the overall design is simplistic.  The script hast no Idea about the content of replacements no matching is done the replacements are just processed in file name sort order.

 

To user this in a script  and be able to process more than one smart object layer there would need to be a que of replacement object for each smart object layer  to be replaced. The ques locations need to have a known folder location for the smart object stack order the sub folders obj0,.....objn. Again no matching is gone the images need to sort so they will populate with the image in the other ques correctly.  The script just process the folders in file name sort order.   The only change to the script dialog is the replacement image ques became a collection of cues via the sub folder the user needs to populate with imaged for each smart object layer. The sub folders name are required to be obj0, obj1, .... objn.     The Replace step was repeated till all the smart object layers in the template were replaced before the jpeg file was saved.  The first script became part of a loop.  The third script the second script became part of a loop.  The dialog was changed to point to a que of templates to be populated. 


 

This is really intresting, thank you so so much for sharing. Last question, do you have a youtube channel or similar where all your script is in action or showcased?

 

Best 

L.Seger